{"record":{"id":"d8f0b47c701da2b1","repo":"remix-run/react-router","slug":"react-router-vite-plugin-can-t-detect-preamble-so","errorCode":null,"errorMessage":"React Router Vite plugin can't detect preamble. Something is wrong.","messagePattern":"React Router Vite plugin can't detect preamble\\. Something is wrong\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":2802,"sourceCode":"  return (\n    REACT_REFRESH_HEADER.replaceAll(\"__SOURCE__\", JSON.stringify(id)) +\n    code +\n    REACT_REFRESH_FOOTER.replaceAll(\"__SOURCE__\", JSON.stringify(id))\n      .replaceAll(\"__ACCEPT_EXPORTS__\", JSON.stringify(acceptExports))\n      .replaceAll(\"__ROUTE_ID__\", JSON.stringify(route?.id))\n  );\n}\n\nconst REACT_REFRESH_HEADER = `\nimport RefreshRuntime from \"${virtualHmrRuntime.id}\";\n\nconst inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;\nlet prevRefreshReg;\nlet prevRefreshSig;\n\nif (import.meta.hot && !inWebWorker) {\n  if (!window.__vite_plugin_react_preamble_installed__) {\n    throw new Error(\n      \"React Router Vite plugin can't detect preamble. Something is wrong.\"\n    );\n  }\n\n  prevRefreshReg = window.$RefreshReg$;\n  prevRefreshSig = window.$RefreshSig$;\n  window.$RefreshReg$ = (type, id) => {\n    RefreshRuntime.register(type, __SOURCE__ + \" \" + id)\n  };\n  window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;\n}`.replaceAll(\"\\n\", \"\"); // Header is all on one line so source maps aren't affected\n\nconst REACT_REFRESH_FOOTER = `\nif (import.meta.hot && !inWebWorker) {\n  window.$RefreshReg$ = prevRefreshReg;\n  window.$RefreshSig$ = prevRefreshSig;\n  RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {\n    RefreshRuntime.registerExportsForReactRefresh(__SOURCE__, currentExports);","sourceCodeStart":2784,"sourceCodeEnd":2820,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/plugin.ts#L2784-L2820","documentation":"This is a runtime error thrown from a header React Router injects into route modules during dev when React Fast Refresh is active. Before using `window.$RefreshReg$`, it checks `window.__vite_plugin_react_preamble_installed__`, which the dev server's react-refresh preamble sets on first load. If a route module executes without that preamble having run (e.g. the page was loaded outside the dev server's HTML, or the runtime was never initialized), refresh registration cannot proceed and this error surfaces in the browser console.","triggerScenarios":"Loading a transformed route module in a context where the react-refresh preamble did not run: opening the built/deployed app while Vite's dev transform is cached; an HTML page served outside the Vite dev server importing dev-server module URLs; testing in jsdom/happy-dom without the preamble globals; worker contexts are explicitly excluded, but custom entries that skip the standard index.html flow can still hit it.","commonSituations":"Importing `http://localhost:5173/app/root.tsx` from a separate static host or Storybook; service-worker or web-worker experiments loading route modules; stale hard-cached HTML after toggling the React Router plugin config; browser extensions re-executing scripts.","solutions":["Always load the app through the Vite dev server's own page (`http://localhost:5173/`) rather than importing transformed modules from another origin or test harness","Hard-refresh and clear cache after changing React Router/Vite React plugin configuration","In test environments (jsdom), don't load dev-transformed modules; run tests against source with Jest/Vitest transformers instead","Ensure only one copy of the React Router plugin and one React refresh runtime is active (no duplicated plugin entries)"],"exampleFix":"// before (storybook/preview or static page) — loads dev-transformed modules directly\nimport Root from 'http://localhost:5173/app/root.tsx';\n\n// after — run the app inside the Vite dev server, or alias source in tests\n// vitest.config.ts\nexport default defineConfig({\n  resolve: { alias: { '~': path.resolve(__dirname, 'app') } },\n});","handlingStrategy":"validation","validationCode":"// In test harnesses, install the preamble flag before importing dev modules\n// (only if you must load dev-transformed code)\n(window as any).__vite_plugin_react_preamble_installed__ = true;","typeGuard":"const preambleInstalled = (): boolean =>\n  typeof window !== 'undefined' &&\n  Boolean((window as { __vite_plugin_react_preamble_installed__?: boolean })\n    .__vite_plugin_react_preamble_installed__);","tryCatchPattern":null,"preventionTips":["Always load the app via the Vite dev server's own index page, never import transformed module URLs from other origins","Run unit tests against source with proper transformers, not the dev server","Hard-refresh after changing Vite/React Router plugin setup"],"tags":["dev","hmr","react-refresh","browser"],"backgroundTag":"react-refresh-preamble-missing","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}