{"record":{"id":"87a1d7b7f0f5b71d","repo":"sveltejs/kit","slug":"cannot-return-redirect-use-redirect","errorCode":null,"errorMessage":"Cannot `return redirect(...)` — use `redirect(...)` instead","messagePattern":"Cannot `return redirect\\(\\.\\.\\.\\)` — use `redirect\\(\\.\\.\\.\\)` instead","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/kit/src/runtime/server/page/actions.js","lineNumber":279,"sourceCode":"\t\t\t\taction(traced_event)\n\t\t\t);\n\n\t\t\tif (result instanceof ActionFailure) {\n\t\t\t\tcurrent.setAttributes({\n\t\t\t\t\t'sveltekit.form_action.result.type': 'failure',\n\t\t\t\t\t'sveltekit.form_action.result.status': result.status\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\t});\n}\n\n/** @param {any} data */\nfunction validate_action_return(data) {\n\tif (data instanceof Redirect) {\n\t\tthrow new Error('Cannot `return redirect(...)` — use `redirect(...)` instead');\n\t}\n\n\tif (data instanceof HttpError) {\n\t\tthrow new Error('Cannot `return error(...)` — use `error(...)` or `return fail(...)` instead');\n\t}\n}\n\n/**\n * Try to `devalue.uneval` the data object, and if it fails, return a proper Error with context\n * @param {any} data\n * @param {string} route_id\n */\nexport function uneval_action_response(data, route_id) {\n\treturn try_serialize(data, uneval, route_id);\n}\n\n/**\n * @param {any} data","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/runtime/server/page/actions.js#L261-L297","documentation":"SvelteKit's `redirect(303, url)` throws a special `Redirect` internal object to abort execution; the framework catches it at the request boundary. Returning the `Redirect` instance from an action breaks that contract, so `validate_action_return` throws to force the correct throw-style usage.","triggerScenarios":"Writing `return redirect(303, '/path')` instead of `throw redirect(303, '/path')` inside a `+page.server.js` action (or load/runner that flows through the action return validator).","commonSituations":"Copy-pasted `return error(...)`/`return redirect(...)` from outdated blog posts or AI snippets; SvelteKit 1.x to newer migration where `redirect()` used to be thrown by `@sveltejs/kit` differently; confusion with returning other values from actions.","solutions":["Replace `return redirect(status, location)` with `throw redirect(status, location)`","Import `redirect` from '@sveltejs/kit' and ensure no code catches the thrown Redirect before SvelteKit handles it"],"exampleFix":"// before\nexport const actions = {\n  logout: async () => {\n    return redirect(303, '/');\n  }\n};\n// after\nimport { redirect } from '@sveltejs/kit';\nexport const actions = {\n  logout: async () => {\n    redirect(303, '/');\n  }\n};","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call `redirect(...)` without return/throw keyword — it throws itself","Enable the eslint rule / review lints warning on returning kit helpers","Update team snippets and AI prompts to SvelteKit 2 semantics"],"tags":["sveltekit","redirect","form-actions","api-misuse"],"backgroundTag":"redirect-must-throw","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}