{"record":{"id":"aeeb20f6e22bba0f","repo":"vercel/next.js","slug":"invalid-revalidate-value-revalidateval-on","errorCode":null,"errorMessage":"Invalid revalidate value \"${revalidateVal}\" on \"${route}\", must be a non-negative number or false","messagePattern":"Invalid revalidate value \"(.+?)\" on \"(.+?)\", must be a non-negative number or false","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/next/src/server/lib/patch-fetch.ts","lineNumber":115,"sourceCode":"export function validateRevalidate(\n  revalidateVal: unknown,\n  route: string\n): undefined | number {\n  try {\n    let normalizedRevalidate: number | undefined = undefined\n\n    if (revalidateVal === false || revalidateVal === Infinity) {\n      // Unlike Infinity, INFINITE_CACHE survives JSON serialization (e.g. in\n      // the fetch cache).\n      normalizedRevalidate = INFINITE_CACHE\n    } else if (\n      typeof revalidateVal === 'number' &&\n      !isNaN(revalidateVal) &&\n      revalidateVal > -1\n    ) {\n      normalizedRevalidate = revalidateVal\n    } else if (typeof revalidateVal !== 'undefined') {\n      throw new Error(\n        `Invalid revalidate value \"${revalidateVal}\" on \"${route}\", must be a non-negative number or false`\n      )\n    }\n    return normalizedRevalidate\n  } catch (err: any) {\n    // handle client component error from attempting to check revalidate value\n    if (err instanceof Error && err.message.includes('Invalid revalidate')) {\n      throw err\n    }\n    return undefined\n  }\n}\n\nexport function validateTags(tags: any[], description: string) {\n  const validTags: string[] = []\n  const invalidTags: Array<{\n    tag: any\n    reason: string","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/packages/next/src/server/lib/patch-fetch.ts#L97-L133","documentation":"Thrown by validateRevalidate when a route's revalidate export or a fetch() revalidate option is a value that is neither false, Infinity, undefined, nor a non-negative finite number. The revalidate contract requires a non-negative number or false to define ISR caching behavior.","triggerScenarios":"A page exports `export const revalidate = '60'` (string), `revalidate = -1`, `revalidate = null`, or a fetch is called with `{ revalidate: 'abc' }`. validateRevalidate normalizes then throws for anything outside the allowed set.","commonSituations":"Passing revalidate as a string (common copy-paste mistake), using a negative number, NaN, or a boolean true. Also happens when revalidate is computed dynamically and yields an unexpected type.","solutions":["Change the revalidate value to a literal non-negative number (e.g. 60) or false.","Remove quotes around the value: revalidate = 60, not '60'.","If computing revalidate at runtime, coerce with Number() and validate it is finite and >= 0 before exporting.","For fetch(), pass { revalidate: 3600 } or { revalidate: false }, never a string or null."],"exampleFix":"// before\nexport const revalidate = '60' // string -> throws\n\n// after\nexport const revalidate = 60 // non-negative number","handlingStrategy":"validation","validationCode":"function validateRevalidate(v: unknown): number | false {\n  if (v === false || v === Infinity) return false\n  if (typeof v === 'number' && !isNaN(v) && v >= 0) return v\n  throw new Error('revalidate must be a non-negative number or false')\n}","typeGuard":"function isValidRevalidate(v: unknown): v is number | false {\n  return v === false || (typeof v === 'number' && !isNaN(v) && v >= 0)\n}","tryCatchPattern":"null","preventionTips":["Always export revalidate as a literal number or false, never a string.","Lint against string literals in revalidate exports.","When computing revalidate, coerce and validate before export."],"tags":["fetch","revalidate","isr","config"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}