{"record":{"id":"ef6fea342c919043","repo":"remix-run/react-router","slug":"detected-a-manifest-version-mismatch-during-eager","errorCode":null,"errorMessage":"Detected a manifest version mismatch during eager route discovery. The next navigation/fetch to an undiscovered route will result in a new document navigation to sync up with the latest manifest.","messagePattern":"Detected a manifest version mismatch during eager route discovery\\. The next navigation/fetch to an undiscovered route will result in a new document navigation to sync up with the latest manifest\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/react-router/lib/dom/ssr/fog-of-war.ts","lineNumber":259,"sourceCode":"): Promise<boolean> {\n  if (!needsReload) {\n    // Reset loop-detection on a successful response\n    try {\n      sessionStorage.removeItem(MANIFEST_VERSION_STORAGE_KEY);\n    } catch {\n      // Session storage unavailable\n    }\n    return false;\n  }\n\n  if (!errorReloadPath) {\n    // No-op during eager route discovery so we will trigger a hard reload\n    // of the destination during the next navigation instead of reloading\n    // while the user is sitting on the current page. Slightly more\n    // disruptive on fetcher calls because we reload the current page, but\n    // it's better than the `React.useContext` error that occurs without\n    // this detection.\n    console.warn(\n      \"Detected a manifest version mismatch during eager route discovery. \" +\n        \"The next navigation/fetch to an undiscovered route will result in \" +\n        \"a new document navigation to sync up with the latest manifest.\",\n    );\n    return true;\n  }\n\n  try {\n    // This will hard reload the destination path on navigations, or the\n    // current path on fetcher calls\n    if (sessionStorage.getItem(MANIFEST_VERSION_STORAGE_KEY) === version) {\n      // We've already tried fixing for this version, don't try again to\n      // avoid loops - just let this navigation/fetch 404\n      console.error(\n        \"Unable to discover routes due to manifest version mismatch.\",\n      );\n      return true;\n    }","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/remix-run/react-router/blob/7aea711dd1ae2bc5a076d13ff17291829690fa74/packages/react-router/lib/dom/ssr/fog-of-war.ts#L241-L277","documentation":"The fog-of-war version-mismatch machinery in two modes: here it fires during eager route discovery (links/forms present at initial load) when a fetched manifest patch has a different version than the page's baked-in manifest, and errorReloadPath is null. Rather than hard-reloading while the user sits on the page, it warns and returns true so the NEXT navigation/fetch to an undiscovered route degrades to a full document load that syncs manifests — avoiding both a disruptive immediate reload and the `React.useContext` crash that would otherwise occur.","triggerScenarios":"Eager discovery fetches /__manifest patches after the server deployed a new build (or a proxy/CDN serves a mismatched version) while errorReloadPath is unavailable — the mismatch is deferred to the next navigation.","commonSituations":"Deploys happening while users hold tabs open; stale-cached manifest or HTML at the edge; rolling deploys serving mixed versions; test environments rebuilt frequently while browser tabs persist.","solutions":["No app fix required — the next navigation performs one full document load and resyncs; this is the designed recovery path","Send `Cache-Control: no-store` for /__manifest and index HTML so patch fetches always reflect the live build","Deploy atomically (single cutover to the new build) so the document and manifest versions never straddle two builds","If every navigation does a full load, all builds in rotation must be reconciled: purge CDN caches and confirm every instance serves one version"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// framework-internal: warns once and defers a document navigation;\n// if you add a version ping, follow the same one-shot guard:\nlet key = \"app-version\";\nif (latestVersion !== embeddedVersion && sessionStorage.getItem(key) !== latestVersion) {\n  sessionStorage.setItem(key, latestVersion);\n  location.reload();\n}","preventionTips":["Mark /__manifest and HTML no-store at the CDN/adapter level","Deploy builds atomically so eager-discovery fetches can't mix two versions","In test/preview environments that rebuild often, close stale tabs or hard-reload after redeploying"],"tags":["fog-of-war","manifest","deploy","stale-client","lazy-routes"],"backgroundTag":"stale-client-after-deploy","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"}