sveltejs/kit · error · Error
Invalid redirect location ${JSON.stringify(location)}: this
Error message
Invalid redirect location ${JSON.stringify(location)}: this string contains characters that cannot be used in HTTP headers What it means
The `Redirect` class validates that the `location` string can be safely placed in a `Location` HTTP header. If `new Headers({ location })` throws — e.g. the string contains newlines, control characters, or other invalid header characters — the redirect is rejected rather than risking header injection or malformed responses.
Source
Thrown at packages/kit/src/exports/internal/shared.js:35
/**
* An `HttpError` whose body is already in its final, user-facing form — either produced by the
* `handleError` hook on the server and reconstructed here from the response, or authored directly
* by the client runtime. Unlike a plain `HttpError` (which represents a fresh `error(...)` call
* that the hook has yet to see), `handleError` must not run on it.
* @extends HttpError
*/
export class HandledHttpError extends HttpError {}
export class Redirect {
/**
* @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status
* @param {string} location
*/
constructor(status, location) {
try {
new Headers({ location });
} catch {
throw new Error(
`Invalid redirect location ${JSON.stringify(location)}: ` +
'this string contains characters that cannot be used in HTTP headers'
);
}
this.status = status;
this.location = location;
}
}
/**
* An error that was thrown from within the SvelteKit runtime that is not fatal and doesn't result in a 500, such as a 404.
* `SvelteKitError` goes through `handleError`.
* @extends Error
*/
export class SvelteKitError extends Error {
/**
* @param {number} statusView on GitHub (pinned to 03f1687fe6)
Solutions
- Sanitize the location before redirecting: trim whitespace and strip or reject control characters (`/[\u0000-\u001F\u007F]/`).
- Validate the target against an allowlist of paths or origins before calling `redirect`.
- Use `encodeURI`/`encodeURIComponent` for user-derived path segments.
- If the input is untrusted and validation fails, redirect to a safe default (e.g. `/`) instead.
Example fix
// before
redirect(302, formData.get('next'));
// after
const next = String(formData.get('next') ?? '/');
if (!/^[\u0021-\u007E]+$/.test(next) || !next.startsWith('/')) redirect(302, '/');
else redirect(302, next); Defensive patterns
Strategy: validation
Validate before calling
function safeLocation(loc) {
const s = String(loc).trim();
return /[\u0000-\u001F\u007F]/.test(s) ? null : s;
}
const loc = safeLocation(input);
if (!loc) redirect(302, '/'); Type guard
const isHeaderSafe = (s) => typeof s === 'string' && s.length > 0 && !/[\u0000-\u001F\u007F]/.test(s);
Try / catch
try {
new Headers({ location: target });
redirect(302, target);
} catch {
redirect(302, '/'); // safe fallback
} Prevention
- Never pass raw user input as the location header value.
- Strip control characters and trim before redirecting.
- Prefer relative paths for internal navigation.
- Treat newline characters in redirect targets as an injection attempt.
When it happens
Trigger: Calling `redirect(302, userInput)` where the input contains `\n`, `\r`, or other non-printable/control characters; building a location from decoded data with embedded newlines.
Common situations: Redirecting to a URL taken verbatim from a query parameter or form field that contains encoded line breaks; log-parsing or copy-paste artifacts introducing newlines into the target URL (a classic open-redirect/header-injection vector).
Related errors
- Invalid status code
- Cannot redirect to external URL ${JSON.stringify(location)}.
- Cannot redirect to ${JSON.stringify(location)} with `{ exter
- The ${protocol_header} header specified ${protocol} which is
- ${keypath} cannot be empty
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/f80f73d9ef068df3.
Report an issue: GitHub.