{"record":{"id":"37f71676a4aca388","repo":"remix-run/react-router","slug":"the-prerender-concurrency-config-must-be-a-posit","errorCode":null,"errorMessage":"The `prerender.concurrency` config must be a positive integer if specified.","messagePattern":"The `prerender\\.concurrency` config must be a positive integer if specified\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/react-router-dev/config/config.ts","lineNumber":579,"sourceCode":"          \"of string paths, or a function returning a boolean or array of string paths.\",\n      );\n    }\n\n    if (typeof prerender === \"object\" && \"unstable_concurrency\" in prerender) {\n      return err(\n        \"The `prerender.unstable_concurrency` config field has been stabilized as `prerender.concurrency`\",\n      );\n    }\n\n    let isValidConcurrencyConfig =\n      typeof prerender != \"object\" ||\n      !(\"concurrency\" in prerender) ||\n      (typeof prerender.concurrency === \"number\" &&\n        Number.isInteger(prerender.concurrency) &&\n        prerender.concurrency > 0);\n\n    if (!isValidConcurrencyConfig) {\n      return err(\n        \"The `prerender.concurrency` config must be a positive integer if specified.\",\n      );\n    }\n  }\n\n  let routeDiscovery: ResolvedReactRouterConfig[\"routeDiscovery\"];\n  if (userRouteDiscovery == null) {\n    if (ssr) {\n      routeDiscovery = {\n        mode: \"lazy\",\n        manifestPath: \"/__manifest\",\n      };\n    } else {\n      routeDiscovery = { mode: \"initial\" };\n    }\n  } else if (userRouteDiscovery.mode === \"initial\") {\n    routeDiscovery = userRouteDiscovery;\n  } else if (userRouteDiscovery.mode === \"lazy\") {","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/remix-run/react-router/blob/6beaca39526d5716c3c112ebb0782765baa5a9ce/packages/react-router-dev/config/config.ts#L561-L597","documentation":"When `prerender` is an object with a `concurrency` key, the value must be a positive integer (`Number.isInteger(n) && n > 0`). Any other value — 0, negative numbers, floats like 2.5, `Infinity`, `NaN`, or strings — fails `isValidConcurrencyConfig` and returns this error, because the value is used to size the prerender worker/task pool.","triggerScenarios":"Setting `prerender: { concurrency: 0 }` (perhaps intending 'unlimited'), a fractional value from a computed config (`Math.log2(cpus)`), or a value parsed from an env string (`process.env.CONCURRENCY` yields `\"4\"`, not `4`).","commonSituations":"Deriving concurrency from `navigator.hardwareConcurrency`-style math that yields non-integers; reading it from env vars without `parseInt`; copying a config that assumed 0 meant unlimited.","solutions":["Set an explicit positive integer, e.g. `concurrency: 4`.","Coerce computed/env values: `concurrency: Number.parseInt(String(process.env.PRERENDER_CONCURRENCY ?? \"4\"), 10)` and clamp to >= 1.","Remove the `concurrency` key to accept the default."],"exampleFix":"// before\nexport default {\n  prerender: { concurrency: Number(process.env.PRERENDER_CONCURRENCY ?? \"4.5\") },\n};\n\n// after\nexport default {\n  prerender: {\n    concurrency: Math.max(1, Number.parseInt(String(process.env.PRERENDER_CONCURRENCY ?? \"4\"), 10)),\n  },\n};","handlingStrategy":"validation","validationCode":"function toConcurrency(raw: unknown): number | undefined {\n  const n = typeof raw === \"number\" ? raw : Number.parseInt(String(raw ?? \"\"), 10);\n  return Number.isInteger(n) && n > 0 ? n : undefined;\n}\n// config: prerender: { concurrency: toConcurrency(process.env.PRERENDER_CONCURRENCY) ?? 4 }","typeGuard":"function isPositiveInteger(v: unknown): v is number {\n  return typeof v === \"number\" && Number.isInteger(v) && v > 0;\n}","tryCatchPattern":null,"preventionTips":["Always parseInt env-derived values and clamp to >= 1.","Avoid floating-point math when deriving worker counts (use Math.ceil/Math.round).","If unsure, omit `concurrency` and accept the default."],"tags":["config","prerender","validation","concurrency"],"backgroundTag":"invalid-config-value","analyzedSha":"6beaca39526d5716c3c112ebb0782765baa5a9ce","analyzedAt":"2026-08-18T18:04:14.938Z","contentChangedAt":"2026-08-18T18:04:14.938Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}