Skip to content

[Bug Report][4.0.4] SSR crash in useFocusTrap: onScopeDispose accesses document without IN_BROWSER guard #22762

@BatLeDev

Description

@BatLeDev

Environment

Vuetify Version: 4.0.4
Vue Version: 3.5.31+
OS: Any (server-side rendering context)

Steps to reproduce

  1. Use Nuxt (or any SSR framework) with Vuetify 4.0.4 and Vue 3.5.31+
  2. Render any component using useFocusTrap (e.g. VDialog, VMenu with retainFocus, VSelect)
  3. Request the page server-side

Expected Behavior

SSR rendering completes without errors.

Actual Behavior

SSR crashes with:

Error: Cannot read properties of undefined (reading 'removeEventListener')
  at Array.<anonymous> (node_modules/vuetify/lib/composables/focusTrap.js:129:14)
  at EffectScope.stop (@vue/reactivity/dist/reactivity.cjs.js:124:25)
  at cleanupContext (@vue/server-renderer/dist/server-renderer.cjs.js:662:15)
  at renderToString (@vue/server-renderer/dist/server-renderer.cjs.js:1014:5)

Root cause

Vue 3.5.31 fixed a bug where EffectScope.stop() was not executing onScopeDispose callbacks during SSR (vue-core#14548). With the fix, Vue now correctly calls those callbacks on the server — but Vuetify's onScopeDispose in composables/focusTrap.js calls document.removeEventListener directly without an IN_BROWSER guard:

if (IN_BROWSER) {
  // ✅ setup listeners correctly guarded
}

onScopeDispose(() => {
  registry.delete(trapId);
  clearTimeout(focusTrapSuppressionTimeout);
  document.removeEventListener('pointerdown', onPointerdown);   // ❌ not guarded
  document.removeEventListener('focusin', captureOnFocus);
  document.removeEventListener('keydown', captureOnKeydown);
  if (--subscribers < 1) {
    document.removeEventListener('keydown', onKeydown);
  }
});

On the server, document is undefined, causing the crash.

Workaround: pin Vue to 3.5.30 until a fix is released.

Expected fix: wrap the document.removeEventListener calls inside onScopeDispose with the same IN_BROWSER check used in the setup block.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions