sveltejs/kit · error · Error

Invalid cache-control directive "${invalid}". Did you mean o

Error message

Invalid cache-control directive "${invalid}". Did you mean one of: ${[...VALID_CACHE_CONTROL_DIRECTIVES].join(', ')}? ${error_suffix}

What it means

Header validation applied to cache-control values set by the app: each comma-separated directive (the part before '=') is checked against the known cache-control directive set, and an unrecognized token triggers this error, including the offending token, the valid list, and a hint that it may be a typo.

Source

Thrown at packages/kit/src/runtime/server/validate-headers.js:35

	'min-fresh'
]);

const CONTENT_TYPE_PATTERN =
	/^(application|audio|example|font|haptics|image|message|model|multipart|text|video|x-[a-z]+)\/[-+.\w]+$/i;

/** @type {Record<string, (value: string) => void>} */
const HEADER_VALIDATORS = {
	'cache-control': (value) => {
		const error_suffix = `(While parsing "${value}".)`;
		const parts = value.split(',').map((part) => part.trim());
		if (parts.some((part) => !part)) {
			throw new Error(`\`cache-control\` header contains empty directives. ${error_suffix}`);
		}

		const directives = parts.map((part) => part.split('=')[0].toLowerCase());
		const invalid = directives.find((directive) => !VALID_CACHE_CONTROL_DIRECTIVES.has(directive));
		if (invalid) {
			throw new Error(
				`Invalid cache-control directive "${invalid}". Did you mean one of: ${[...VALID_CACHE_CONTROL_DIRECTIVES].join(', ')}? ${error_suffix}`
			);
		}
	},

	'content-type': (value) => {
		const type = value.split(';')[0].trim();
		const error_suffix = `(While parsing "${value}".)`;
		if (!CONTENT_TYPE_PATTERN.test(type)) {
			throw new Error(`Invalid content-type value "${type}". ${error_suffix}`);
		}
	}
};

/**
 * @param {Record<string, string>} headers
 */
export function validateHeaders(headers) {

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Correct the directive name to one from the listed valid set (no-store, no-cache, must-revalidate, public, private, max-age, s-maxage, immutable, stale-while-revalidate, etc.)
  2. Split custom/proprietary directives out — SvelteKit only validates cache-control; use another header name for non-standard policies
  3. Check spelling case-insensitively: the validator lowercases, so 'Pulbic' still fails

Example fix

// before
event.setHeaders({ 'cache-control': 'pulbic, max-age=3600' });
// after
event.setHeaders({ 'cache-control': 'public, max-age=3600' });
Defensive patterns

Strategy: validation

Validate before calling

const VALID = new Set(['no-store','no-cache','must-revalidate','proxy-revalidate','must-understand','immutable','public','private','max-age','s-maxage','max-stale','min-fresh','stale-while-revalidate','stale-if-error','only-if-cached','no-transform']);
function validateCacheControl(value) {
  for (const part of value.split(',')) {
    const d = part.trim().split('=')[0].toLowerCase();
    if (!VALID.has(d)) throw new Error('Invalid cache-control directive: ' + d);
  }
}

Try / catch

try {
  event.setHeaders({ 'cache-control': cc });
} catch (e) {
  if (e.message.startsWith('Invalid cache-control directive')) console.error('Typo in directive:', cc);
}

Prevention

When it happens

Trigger: setHeaders({ 'cache-control': 'max-age=60, pulbic' }) (typo for public); using non-standard directives like 'immutable ' misspelled or 'no-cache-store'; camelCase variants like 'Max-Age' are lowercased and fine, but wrong words are not.

Common situations: Hand-typed cache policies with typos; copying CDN-specific directives (e.g. s-maxage is valid, but 'stale-if-error' must be spelled exactly) that the validator doesn't recognize.

Related errors


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