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

  1. Set `expiration` to a positive number of seconds, e.g. `isr: { expiration: 60 }`
  2. Use `expiration: false` if you want the maximum (1 year) caching
  3. Remove non-numeric strings or convert them to seconds yourself
  4. 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

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


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/0e0d14642a2ac036. Report an issue: GitHub.