{"record":{"id":"e0099a55866b31b3","repo":"angular/angular-cli","slug":"invalid-redirect-status-code-status-please-us","errorCode":null,"errorMessage":"Invalid redirect status code: ${status}. Please use one of the following redirect response codes: ${[...VALID_REDIRECT_RESPONSE_CODES.values()].join(', ')}.","messagePattern":"Invalid redirect status code: (.+?)\\. Please use one of the following redirect response codes: (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/angular/ssr/src/utils/redirect.ts","lineNumber":41,"sourceCode":"  return VALID_REDIRECT_RESPONSE_CODES.has(code);\n}\n\n/**\n * Creates an HTTP redirect response with a specified location and status code.\n *\n * @param location - The URL to which the response should redirect.\n * @param status - The HTTP status code for the redirection. Defaults to 302 (Found).\n *                 See: https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect_static#status\n * @param headers - Additional headers to include in the response.\n * @returns A `Response` object representing the HTTP redirect.\n */\nexport function createRedirectResponse(\n  location: string,\n  status = 302,\n  headers?: Record<string, string> | Headers,\n): Response {\n  if (ngDevMode && !isValidRedirectResponseCode(status)) {\n    throw new Error(\n      `Invalid redirect status code: ${status}. ` +\n        `Please use one of the following redirect response codes: ${[...VALID_REDIRECT_RESPONSE_CODES.values()].join(', ')}.`,\n    );\n  }\n\n  const resHeaders = headers instanceof Headers ? headers : new Headers(headers);\n  if (ngDevMode && resHeaders.has('location')) {\n    // eslint-disable-next-line no-console\n    console.warn(\n      `Location header \"${resHeaders.get('location')}\" will be ignored and set to \"${location}\".`,\n    );\n  }\n\n  // Ensure unique values for Vary header\n  const varyArray = resHeaders.get('Vary')?.split(',') ?? [];\n  const varySet = new Set(['X-Forwarded-Prefix']);\n  for (const vary of varyArray) {\n    const value = vary.trim();","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/angular/angular-cli/blob/bb72145f9ab45aee29f523236b3a25cd0813a841/packages/angular/ssr/src/utils/redirect.ts#L23-L59","documentation":"`createRedirectResponse` builds an HTTP redirect `Response` for SSR, and only a fixed set of redirect status codes (301, 302, 303, 307, 308 — `VALID_REDIRECT_RESPONSE_CODES`) is allowed. In dev mode (`ngDevMode`) it throws this error if the provided `status` is outside that set, catching invalid redirect codes (e.g. 200 or 404) early.","triggerScenarios":"Passing a custom `status` to `createRedirectResponse(location, status)` (or the underlying redirect helper) that is not one of the valid redirect codes, e.g. `createRedirectResponse('/login', 200)` or a status read from config as an arbitrary number.","commonSituations":"Language-based redirects (`redirectBasedOnAcceptLanguage`) configured with a wrong default; mapping backend/legacy status codes directly to SSR redirects; typos like 3011 or 304; using 303/308 incorrectly assuming all 3xx are allowed.","solutions":["Use one of the allowed codes: 301 (permanent), 302 (default temporary), 303, 307, or 308.","Replace invalid codes: use 302/307 for temporary redirects and 301/308 for permanent ones (e.g. change 304 or 200 to 302).","If the status comes from configuration/env, validate/clamp it against `isValidRedirectResponseCode()` before calling.","Note the check only runs when `ngDevMode` is truthy — production builds may silently produce a broken response, so fix at the source, not just in dev."],"exampleFix":"// before\nconst res = createRedirectResponse(targetUrl, 304);\n// after\nconst res = createRedirectResponse(targetUrl, 302); // or 301/303/307/308","handlingStrategy":"validation","validationCode":"const VALID = new Set([301, 302, 303, 307, 308]);\nif (!VALID.has(status)) {\n  throw new Error(`status must be one of ${[...VALID].join(', ')}, got ${status}`);\n}\nconst res = createRedirectResponse(location, status, headers);","typeGuard":"function isRedirectStatus(s: number): s is 301 | 302 | 303 | 307 | 308 {\n  return [301, 302, 303, 307, 308].includes(s);\n}","tryCatchPattern":"try {\n  return createRedirectResponse(location, status, headers);\n} catch (e) {\n  if (String(e?.message).startsWith('Invalid redirect status code')) {\n    return createRedirectResponse(location, 302, headers); // safe default\n  }\n  throw e;\n}","preventionTips":["Only use 301, 302, 303, 307, 308 for redirects; never pass arbitrary 3xx/2xx codes.","Type redirect statuses as `301|302|303|307|308` union instead of `number`.","If status comes from config, validate it with `isValidRedirectResponseCode()` first.","Remember the throw only happens in ngDevMode — test redirects in a dev build, don't rely on production to catch it."],"tags":["angular","ssr","redirect","http-status-code","validation"],"backgroundTag":"invalid-redirect-status-code","analyzedSha":"bb72145f9ab45aee29f523236b3a25cd0813a841","analyzedAt":"2026-08-30T02:47:34.745Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}