vercel/next.js · error · Error
Invalid revalidate value "${revalidateVal}" on "${route}", m
Error message
Invalid revalidate value "${revalidateVal}" on "${route}", must be a non-negative number or false What it means
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.
Source
Thrown at packages/next/src/server/lib/patch-fetch.ts:115
export function validateRevalidate(
revalidateVal: unknown,
route: string
): undefined | number {
try {
let normalizedRevalidate: number | undefined = undefined
if (revalidateVal === false || revalidateVal === Infinity) {
// Unlike Infinity, INFINITE_CACHE survives JSON serialization (e.g. in
// the fetch cache).
normalizedRevalidate = INFINITE_CACHE
} else if (
typeof revalidateVal === 'number' &&
!isNaN(revalidateVal) &&
revalidateVal > -1
) {
normalizedRevalidate = revalidateVal
} else if (typeof revalidateVal !== 'undefined') {
throw new Error(
`Invalid revalidate value "${revalidateVal}" on "${route}", must be a non-negative number or false`
)
}
return normalizedRevalidate
} catch (err: any) {
// handle client component error from attempting to check revalidate value
if (err instanceof Error && err.message.includes('Invalid revalidate')) {
throw err
}
return undefined
}
}
export function validateTags(tags: any[], description: string) {
const validTags: string[] = []
const invalidTags: Array<{
tag: any
reason: stringView on GitHub (pinned to 0ae8c72462)
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.
Example fix
// before export const revalidate = '60' // string -> throws // after export const revalidate = 60 // non-negative number
Defensive patterns
Strategy: validation
Validate before calling
function validateRevalidate(v: unknown): number | false {
if (v === false || v === Infinity) return false
if (typeof v === 'number' && !isNaN(v) && v >= 0) return v
throw new Error('revalidate must be a non-negative number or false')
} Type guard
function isValidRevalidate(v: unknown): v is number | false {
return v === false || (typeof v === 'number' && !isNaN(v) && v >= 0)
} Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to fetch ${url}
- `forbidden()` is experimental and only allowed to be enabled
- `unauthorized()` is experimental and only allowed to be used
- NEXT_EXPORT_ERROR
- Proxy request failed: ${resp.status}
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/aeeb20f6e22bba0f.
Report an issue: GitHub.