{"record":{"id":"d0573d92a1bf4c4e","repo":"remix-run/react-router","slug":"the-future-unstable-subresourceintegrity-flag-ha","errorCode":null,"errorMessage":"The `future.unstable_subResourceIntegrity` flag has been stabilized and moved to a top-level `config.subResourceIntegrity` field","messagePattern":"The `future\\.unstable_subResourceIntegrity` flag has been stabilized and moved to a top-level `config\\.subResourceIntegrity` field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/config/config.ts","lineNumber":740,"sourceCode":"    }\n    if (\n      \"unstable_middleware\" in futureConfig ||\n      \"v8_middleware\" in futureConfig\n    ) {\n      return err(\n        \"The `future.v8_middleware` flag has been removed because middleware is now always enabled\",\n      );\n    }\n    if (\n      \"unstable_trailingSlashAwareDataRequests\" in futureConfig ||\n      \"v8_trailingSlashAwareDataRequests\" in futureConfig\n    ) {\n      return err(\n        \"The `future.v8_trailingSlashAwareDataRequests` flag has been removed because trailing slash-aware data requests are now the default behavior\",\n      );\n    }\n    if (\"unstable_subResourceIntegrity\" in futureConfig) {\n      return err(\n        \"The `future.unstable_subResourceIntegrity` flag has been stabilized and moved to a top-level `config.subResourceIntegrity` field\",\n      );\n    }\n  }\n\n  let future: FutureConfig = {\n    unstable_enableNodeReadableStream:\n      userAndPresetConfigs.future?.unstable_enableNodeReadableStream ?? false,\n    unstable_optimizeDeps:\n      userAndPresetConfigs.future?.unstable_optimizeDeps ?? false,\n  };\n\n  let allowedActionOrigins = userAndPresetConfigs.allowedActionOrigins ?? false;\n  let splitRouteModules = userAndPresetConfigs.splitRouteModules ?? true;\n  let subResourceIntegrity = userAndPresetConfigs.subResourceIntegrity ?? false;\n\n  let reactRouterConfig: ResolvedReactRouterConfig = deepFreeze({\n    appDirectory,","sourceCodeStart":722,"sourceCodeEnd":758,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/config/config.ts#L722-L758","documentation":"Fatal config-validation error: `future.unstable_subResourceIntegrity` was stabilized. The option now lives as the top-level `config.subResourceIntegrity` boolean (default false, resolved at config.ts line 755), so keeping the old future key aborts readConfig with instructions to move it. SRI adds integrity hashes to prerendered/asset tags; only the location changed, not the behavior.","triggerScenarios":"Any config-loading run where `future` contains the `unstable_subResourceIntegrity` key (there is no v8_ alias for this one — only the unstable name is checked).","commonSituations":"Apps that enabled SRI when it was unstable and upgraded after stabilization; configs written from older docs; the flag being spread into `future` via a shared object.","solutions":["Move the option to the top level: replace `future: { unstable_subResourceIntegrity: true }` with `subResourceIntegrity: true`","Keep the value semantics: true enables SRI, omit/false disables — nothing else changed","Re-run typegen so `.react-router/types` reflect the top-level field","Remove any `satisfies FutureConfig` typing that still lists the old key"],"exampleFix":"// before - react-router.config.ts\nimport type { Config } from \"@react-router/dev\";\nexport default {\n  future: { unstable_subResourceIntegrity: true },\n} satisfies Config;\n\n// after\nexport default {\n  subResourceIntegrity: true,\n} satisfies Config;","handlingStrategy":"validation","validationCode":"import fs from \"node:fs\";\nlet cfg = fs.readFileSync(\"react-router.config.ts\", \"utf8\");\nif (cfg.includes(\"unstable_subResourceIntegrity\")) {\n  throw new Error(\"Move `future.unstable_subResourceIntegrity` to top-level `subResourceIntegrity`\");\n}","typeGuard":"// guard the moved option on a parsed config object\nfunction hasTopLevelSRI(cfg: unknown): cfg is { subResourceIntegrity: boolean } {\n  if (typeof cfg !== \"object\" || cfg === null) return false;\n  let f = (cfg as { future?: Record<string, unknown> }).future;\n  return !(f && \"unstable_subResourceIntegrity\" in f);\n}","tryCatchPattern":"try {\n  let result = await readConfig(root);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"subResourceIntegrity\")) {\n    // rewrite future.unstable_subResourceIntegrity -> top-level subResourceIntegrity, retry once\n  } else throw e;\n}","preventionTips":["Watch stabilization notes: unstable_ flags that stabilize usually relocate to top-level config fields","Prefer top-level options over future.* flags in new configs; future flags are inherently temporary","Re-run `react-router typegen` after every upgrade so relocated fields surface in types"],"tags":["config","future-flags","sri","upgrade","build-error"],"backgroundTag":"renamed-config-option","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}