sveltejs/kit · error · Error
Invalid isr.expiration value: ${JSON.stringify(value)} (${de
Error message
Invalid isr.expiration value: ${JSON.stringify(value)} (${desc}, in ${route_id}) What it means
adapter-vercel validates the `isr.expiration` value from each route's config via parse_isr_expiration. Valid values are `false`/'false' (meaning 1 year) or a positive number/numeric string; anything else — negative numbers, zero, non-numeric strings, objects — throws with a description of why it is invalid.
Source
Thrown at packages/adapter-vercel/utils.js:34
src = '^/?';
}
return src;
}
const integer = /^\d+$/;
/**
* @param {false | string | number} value
* @param {string} route_id
* @returns {number | false}
*/
export function parse_isr_expiration(value, route_id) {
if (value === false || value === 'false') return false; // 1 year
/** @param {string} desc */
const err = (desc) => {
throw new Error(
`Invalid isr.expiration value: ${JSON.stringify(value)} (${desc}, in ${route_id})`
);
};
let parsed;
if (typeof value === 'string') {
if (!integer.test(value)) {
err('value was a string but could not be parsed as an integer');
}
parsed = Number.parseInt(value, 10);
} else {
if (!Number.isInteger(value)) {
err('should be an integer');
}
parsed = value;
}
if (Number.isNaN(parsed)) {View on GitHub (pinned to 03f1687fe6)
Solutions
- Set `expiration` to a positive number of seconds, e.g. `isr: { expiration: 60 }`
- Use `expiration: false` if you want the maximum (1 year) caching
- Remove non-numeric strings or convert them to seconds yourself
- Check the route named in the error message (`in ${route_id}`) and fix its exported config
Example fix
// before (+page.js)
export const config = { isr: { expiration: '1 hour' } };
// after
export const config = { isr: { expiration: 3600 } }; Defensive patterns
Strategy: validation
Validate before calling
const exp = config?.isr?.expiration;
const valid = exp === false || exp === 'false' || (typeof exp === 'number' && exp > 0) || (typeof exp === 'string' && Number(exp) > 0);
if (!valid) throw new Error(`invalid isr.expiration: ${JSON.stringify(exp)}`); Type guard
const isValidExpiration = (v) => v === false || v === 'false' || (typeof v === 'number' && Number.isFinite(v) && v > 0) || (typeof v === 'string' && v.trim() !== '' && Number(v) > 0);
Try / catch
try {
await build();
} catch (err) {
if (err.message.startsWith('Invalid isr.expiration')) {
console.error('Set isr.expiration to a positive number of seconds or false.');
}
throw err;
} Prevention
- Express expiration always in whole seconds
- Use false (not 0) for maximal caching
- Centralize ISR config constants to avoid one-off typos
- Type-check route configs with JSDoc/TS
When it happens
Trigger: A route exports `config.isr.expiration` that parses to an invalid value: e.g. `expiration: 0`, `expiration: -30`, `expiration: 'soon'`, or a string that Number() cannot parse, in utils.js parse_isr_expiration.
Common situations: Typo like 'expiraton' swapped types; setting expiration to 0 thinking it means 'no cache'; copying an exponential-backoff-style value; passing a Date or human string like '1 hour'.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- ${directory}: `__pathname` is a reserved query parameter for
- The `edge` runtime is no longer supported
- The ${route.id} and ${existing.route_id} routes must be merg
- Unsupported runtime: ${key}. Supported runtimes are: ${valid
- The SvelteKit options from the Vite config must be an object
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/0e0d14642a2ac036.
Report an issue: GitHub.