Skip to content

TDZ error: Cannot access before initialization when bundled with Vite manualChunks #1972

@seunghan91

Description

@seunghan91

Bug Report

Summary

When using bits-ui v2.x with Vite 5 and the manualChunks option to group svelte + bits-ui into a single vendor chunk, a Temporal Dead Zone (TDZ) error occurs at runtime:

Uncaught ReferenceError: Cannot access 'xu' before initialization
    at vendor-svelte-XXXXXXXX.js:10:2286

Environment

  • bits-ui: v2.x (Svelte 5 compatible)
  • svelte: 5.x
  • vite: 5.x
  • @sveltejs/vite-plugin-svelte: latest
  • Framework: Rails 8 + Inertia.js + Svelte 5 (single-server deploy)

Reproduction

vite.config.ts:

build: {
  rollupOptions: {
    output: {
      manualChunks(id) {
        if (id.includes('node_modules')) {
          // ❌ This causes the TDZ error
          if (id.includes('svelte') || id.includes('bits-ui') || id.includes('lucide-svelte'))
            return 'vendor-svelte'
          return 'vendor'
        }
      },
    },
  },
},

Root Cause

bits-ui v2.x (Svelte 5 version) has circular imports between its internal modules. When Rollup is forced to put all these modules into a single chunk via manualChunks, it must linearize the circular dependency graph. The chosen initialization order results in a const binding being accessed before it is initialized (TDZ).

The same error occurs even with these mitigations:

  • externalLiveBindings: false — no effect on the TDZ
  • hoistTransitiveImports: false — changes chunk content but doesn't fix the circular dep ordering
  • optimizeDeps.include: ['bits-ui'] — only affects dev mode, not production builds

Fix

Remove svelte, bits-ui, and related packages from manualChunks and let Rollup handle their chunking automatically:

build: {
  rollupOptions: {
    output: {
      externalLiveBindings: false,
      hoistTransitiveImports: false,
      manualChunks(id) {
        if (id.includes('node_modules')) {
          // ✅ Do NOT force svelte/bits-ui into a manual chunk
          if (id.includes('@inertiajs')) return 'vendor-inertia'
          if (id.includes('date-fns')) return 'vendor-date'
          // ... other non-circular vendors
        }
      },
    },
  },
},

When Rollup auto-chunks the svelte ecosystem, it properly handles the circular dependency ordering and the TDZ error disappears.

Notes

This may be worth documenting in the bits-ui migration guide or FAQ for Vite users. The error is cryptic (minified variable name + no stack trace pointing to user code) and took several deploy iterations to diagnose.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions