{"record":{"id":"eec3f7b2e5e024b4","repo":"remix-run/react-router","slug":"the-future-v8-viteenvironmentapi-flag-has-been-r","errorCode":null,"errorMessage":"The `future.v8_viteEnvironmentApi` flag has been removed because Vite Environment API usage is now always enabled","messagePattern":"The `future\\.v8_viteEnvironmentApi` flag has been removed because Vite Environment API usage is now always enabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/config/config.ts","lineNumber":711,"sourceCode":"    }\n  }\n\n  // Check for renamed flags and provide helpful error messages\n  let futureConfig = userAndPresetConfigs.future;\n  if (futureConfig) {\n    if (\n      \"unstable_splitRouteModules\" in futureConfig ||\n      \"v8_splitRouteModules\" in futureConfig\n    ) {\n      return err(\n        \"The `future.v8_splitRouteModules` flag has been moved to a top-level `config.splitRouteModules` field (default `true`)\",\n      );\n    }\n    if (\n      \"unstable_viteEnvironmentApi\" in futureConfig ||\n      \"v8_viteEnvironmentApi\" in futureConfig\n    ) {\n      return err(\n        \"The `future.v8_viteEnvironmentApi` flag has been removed because Vite Environment API usage is now always enabled\",\n      );\n    }\n    if (\n      \"unstable_passThroughRequests\" in futureConfig ||\n      \"v8_passThroughRequests\" in futureConfig\n    ) {\n      return err(\n        \"The `future.v8_passThroughRequests` flag has been removed because pass-through requests are now the default behavior\",\n      );\n    }\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      );","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/config/config.ts#L693-L729","documentation":"This is a fatal config-validation error from @react-router/dev's readConfig: when react-router.config.ts contains a `future.unstable_viteEnvironmentApi` or `future.v8_viteEnvironmentApi` key, the dev server / build aborts. In this version the Vite Environment API is used unconditionally, so the flag no longer does anything and its presence means the config predates the current major version. The check uses `in` on the future object, so even `viteEnvironmentApi: false` triggers it.","triggerScenarios":"Running `react-router dev`, `react-router build`, typegen, or any code path that calls readConfig while `future` in react-router.config.ts (or a preset/extends config) contains the key `unstable_viteEnvironmentApi` or `v8_viteEnvironmentApi`, with any value including false/null.","commonSituations":"Upgrading a v7 app that opted into the Vite Environment API early; copying an old config from a tutorial or another repo; CI suddenly failing right after bumping @react-router/dev to the next major.","solutions":["Delete the `v8_viteEnvironmentApi` (or `unstable_viteEnvironmentApi`) key from the `future` object in react-router.config.ts — the behavior it enabled is always on now","Grep the repo for `viteEnvironmentApi` to catch the flag in presets, extends configs, comments, and stale FutureConfig typings","Re-run `npx react-router typegen` and `pnpm typecheck` so leftover references to the removed flag surface as type errors","Skim the upgrade guide for the other removed v8_* flags (passThroughRequests, middleware, trailingSlashAwareDataRequests, splitRouteModules, subResourceIntegrity) and clean them all in one pass"],"exampleFix":"// before - react-router.config.ts\nexport default {\n  future: { v8_viteEnvironmentApi: true },\n} satisfies Config;\n\n// after\nexport default {} satisfies Config; // Vite Environment API is always enabled","handlingStrategy":"validation","validationCode":"// run before `react-router dev/build` — fail fast on removed flags\nimport fs from \"node:fs\";\nlet cfg = fs.readFileSync(\"react-router.config.ts\", \"utf8\");\nlet banned = [\"v8_viteEnvironmentApi\", \"unstable_viteEnvironmentApi\"];\nlet hits = banned.filter((k) => cfg.includes(k));\nif (hits.length) {\n  throw new Error(`Remove removed future flags from react-router.config.ts: ${hits.join(\", \")}`);\n}","typeGuard":"// narrows a parsed config to the current (post-removal) FutureConfig shape\ntype CurrentFuture = { unstable_enableNodeReadableStream?: boolean; unstable_optimizeDeps?: boolean };\nfunction isCurrentFutureConfig(f: unknown): f is CurrentFuture {\n  if (typeof f !== \"object\" || f === null) return false;\n  return !(\"v8_viteEnvironmentApi\" in f || \"unstable_viteEnvironmentApi\" in f);\n}","tryCatchPattern":"try {\n  let result = await readConfig(rootDirectory);\n  if (result.ok) run(result.value);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"v8_viteEnvironmentApi\")) {\n    // strip the key from react-router.config.ts and re-run once, then surface to the user\n  } else throw e;\n}","preventionTips":["Treat major-version bumps of @react-router/dev as breaking: read the upgrade guide's removed-flags table before merging","Run `npx react-router typegen && tsc --noEmit` in CI so removed flag keys fail the type check","Keep react-router.config.ts minimal and avoid spreading shared future objects between apps of different versions"],"tags":["config","future-flags","vite","upgrade","build-error"],"backgroundTag":"removed-feature-flag","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"}