{"record":{"id":"1d1006a9a138ed2d","repo":"remix-run/react-router","slug":"you-must-be-using-the-ssr-features-of-react-router","errorCode":null,"errorMessage":"You must be using the SSR features of React Router in order to skip passing a `router` prop to `<RouterProvider>`","messagePattern":"You must be using the SSR features of React Router in order to skip passing a `router` prop to `<RouterProvider>`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router/lib/dom-export/hydrated-router.tsx","lineNumber":89,"sourceCode":"      routeModules: window.__reactRouterRouteModules,\n      stateDecodingPromise: undefined,\n      router: undefined,\n      routerInitialized: false,\n    };\n  }\n}\n\nfunction createHydratedRouter({\n  getContext,\n  instrumentations,\n}: {\n  getContext?: RouterInit[\"getContext\"];\n  instrumentations?: ClientInstrumentation[];\n}): DataRouter {\n  initSsrInfo();\n\n  if (!ssrInfo) {\n    throw new Error(\n      \"You must be using the SSR features of React Router in order to skip \" +\n        \"passing a `router` prop to `<RouterProvider>`\",\n    );\n  }\n\n  // We need to suspend until the initial state snapshot is decoded into\n  // window.__reactRouterContext.state\n\n  let localSsrInfo = ssrInfo;\n  // Note: `stateDecodingPromise` is not coupled to `router` - we'll reach this\n  // code potentially many times waiting for our state to arrive, but we'll\n  // then only get past here and create the `router` one time\n  if (!ssrInfo.stateDecodingPromise) {\n    let stream = ssrInfo.context.stream;\n    invariant(stream, \"No stream found for single fetch decoding\");\n    ssrInfo.context.stream = undefined;\n    ssrInfo.stateDecodingPromise = decodeViaTurboStream(stream, window)\n      .then((value) => {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/remix-run/react-router/blob/7aea711dd1ae2bc5a076d13ff17291829690fa74/packages/react-router/lib/dom-export/hydrated-router.tsx#L71-L107","documentation":"The framework-mode <RouterProvider> (hydrated-router) builds its router from window.__reactRouterContext, __reactRouterManifest, and __reactRouterRouteModules injected by the SSR build. initSsrInfo() finds none of them, so createHydratedRouter throws (lib/dom-export/hydrated-router.tsx89) when you omit the router prop outside that pipeline.","triggerScenarios":"Rendering the framework RouterProvider without a router prop in a manually-built client (Declarative/Data mode app reusing the framework entry); an entry.client.tsx copied into a non-framework setup; SSR pipeline disabled/removed so the hydration globals were never injected.","commonSituations":"Mixing framework-mode entry files into a custom Vite/webpack client; migrating an app off Framework Mode but keeping the generated entry.client.tsx; test harnesses rendering <RouterProvider /> without the SSR context.","solutions":["Pass your own router: <RouterProvider router={createBrowserRouter(routes)} />","Or stay in Framework Mode SSR so the build injects the hydration globals","Do not reuse the generated entry.client.tsx in a non-framework setup; write your own root.tsx/entry"],"exampleFix":"// before\nhydrateRoot(el, <RouterProvider />) // no SSR globals present\n// after\nconst router = createBrowserRouter(routes)\nhydrateRoot(el, <RouterProvider router={router} />)","handlingStrategy":"validation","validationCode":"// Only use the hydrated RouterProvider when the SSR build injected its globals\nconst hasFrameworkGlobals =\n  typeof window !== 'undefined' &&\n  Boolean(window.__reactRouterContext && window.__reactRouterManifest);\nif (!hasFrameworkGlobals) {\n  root = <RouterProvider router={createBrowserRouter(routes)} />;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass an explicit router prop in any non-framework/custom client setup","Don't copy generated framework entry files into manually configured apps","Smoke-render the app entry in CI for both framework and custom setups"],"tags":["ssr","hydration","router-provider","framework-mode","spa"],"backgroundTag":"missing-hydration-data","analyzedSha":"7aea711dd1ae2bc5a076d13ff17291829690fa74","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}