{"record":{"id":"1255f066a5c50266","repo":"remix-run/react-router","slug":"custom-vite-manifest-paths-are-not-supported","errorCode":null,"errorMessage":"Custom Vite manifest paths are not supported","messagePattern":"Custom Vite manifest paths are not supported","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/vite/plugin.ts","lineNumber":126,"sourceCode":"  root,\n  plugins,\n}: {\n  configFile?: string;\n  mode?: string;\n  plugins?: Vite.Plugin[];\n  root: string;\n}) {\n  let vite = getVite();\n\n  let viteConfig = await vite.resolveConfig(\n    { mode, configFile, root, plugins },\n    \"build\", // command\n    \"production\", // default mode\n    \"production\", // default NODE_ENV\n  );\n\n  if (typeof viteConfig.build.manifest === \"string\") {\n    throw new Error(\"Custom Vite manifest paths are not supported\");\n  }\n\n  return viteConfig;\n}\n\nexport function extractPluginContext(\n  viteConfig: Vite.ResolvedConfig | Vite.UserConfig,\n) {\n  return viteConfig[\"__reactRouterPluginContext\" as keyof typeof viteConfig] as\n    | ReactRouterPluginContext\n    | undefined;\n}\n\nconst SERVER_ONLY_ROUTE_EXPORTS = [\"loader\", \"action\", \"middleware\", \"headers\"];\nconst CLIENT_NON_COMPONENT_EXPORTS = [\n  \"clientAction\",\n  \"clientLoader\",\n  \"clientMiddleware\",","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/vite/plugin.ts#L108-L144","documentation":"When React Router resolves the Vite config for its child compilers, it checks `viteConfig.build.manifest`. The framework reads the Vite manifest from its well-known default location to map route modules to built assets, so a custom manifest path string is rejected outright. This is a compatibility guard: RR post-processes the manifest itself and cannot follow a relocated one.","triggerScenarios":"Setting `build.manifest: 'custom/manifest.json'` (any string) in vite.config.ts while the React Router Vite plugin is active; copying a shared Vite config from a non-React Router project that customizes the manifest path; enabling `build.manifest` with a path via a shared config preset.","commonSituations":"Teams reusing an existing Vite config that set `build.manifest` for their own asset pipeline; CI configs that centralized `manifest: 'dist/manifest.json'`; upgrading to Framework Mode while keeping legacy Vite build options.","solutions":["Remove the custom string from `build.manifest` in vite.config.ts and let it stay `true`/unset so Vite emits `.vite/manifest.json` at the default path","If you need the manifest for another tool, read it from `build/assets/.vite/manifest.json` after the build instead of relocating it","Scope any custom Vite build config used by other apps away from the React Router app's vite.config.ts"],"exampleFix":"// before (vite.config.ts)\nexport default defineConfig({\n  build: { manifest: 'dist/rr-manifest.json' },\n});\n\n// after\nexport default defineConfig({\n  build: { manifest: true }, // default .vite/manifest.json location\n});","handlingStrategy":"validation","validationCode":"// Pre-flight check before running react-router build\nimport type { UserConfig } from 'vite';\nconst cfg: UserConfig = { /* ... */ };\nif (typeof cfg.build?.manifest === 'string') {\n  throw new Error('React Router does not support a custom build.manifest path');\n}\nexport default cfg;","typeGuard":"const hasCustomManifestPath = (cfg: { build?: { manifest?: unknown } }): boolean =>\n  typeof cfg.build?.manifest === 'string';","tryCatchPattern":"try {\n  await build();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('manifest paths are not supported')) {\n    console.error('Remove build.manifest path from vite.config.ts and retry');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Never set `build.manifest` to a string in a React Router project","Consume the manifest at its default path `build/client/.vite/manifest.json` in downstream tooling","Lint shared Vite configs to forbid `build.manifest` string overrides"],"tags":["vite","config","build","manifest"],"backgroundTag":"vite-config-incompatible","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"}