{"id":"3fff7a0328aa5af9","repo":"gin-gonic/gin","slug":"cannot-redirect-with-status-code-d","errorCode":null,"errorMessage":"Cannot redirect with status code %d","messagePattern":"Cannot redirect with status code (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"render/redirect.go","lineNumber":22,"sourceCode":"\npackage render\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n)\n\n// Redirect contains the http request reference and redirects status code and location.\ntype Redirect struct {\n\tCode     int\n\tRequest  *http.Request\n\tLocation string\n}\n\n// Render (Redirect) redirects the http request to new location and writes redirect response.\nfunc (r Redirect) Render(w http.ResponseWriter) error {\n\tif (r.Code < http.StatusMultipleChoices || r.Code > http.StatusPermanentRedirect) && r.Code != http.StatusCreated {\n\t\tpanic(fmt.Sprintf(\"Cannot redirect with status code %d\", r.Code))\n\t}\n\thttp.Redirect(w, r.Request, r.Location, r.Code)\n\treturn nil\n}\n\n// WriteContentType (Redirect) don't write any ContentType.\nfunc (r Redirect) WriteContentType(http.ResponseWriter) {}\n","sourceCodeStart":4,"sourceCodeEnd":30,"githubUrl":"https://github.com/gin-gonic/gin/blob/34dac209ffb6ef85cc78c5d217bbb7ad001d68fd/render/redirect.go#L4-L30","documentation":"Redirect.Render (render/redirect.go:22) panics when the status code is outside the HTTP redirect range [300, 308] and is not 201. http.Redirect only accepts 3xx codes (plus 201 Created with a Location), so any other code (200, 404, 500, etc.) is a programmer error and Gin aborts.","triggerScenarios":"Calling c.Redirect(http.StatusMovedPermanently, ...) — wait that's valid; calling c.Redirect(http.StatusOK, url) (200 is not a redirect code); c.Redirect(http.StatusFound, ...) is valid but c.Redirect(200, url) panics; passing a custom int that is not 3xx and not 201.","commonSituations":"Using http.StatusOK or http.StatusBadRequest as the redirect status by mistake; using an enum/constant that resolves to a non-3xx value; copying c.JSON(status, ...) patterns into c.Redirect.","solutions":["Use a valid redirect status: 301 (MovedPermanently), 302 (Found), 303 (SeeOther), 307 (TemporaryRedirect), 308 (PermanentRedirect), or 201 (Created) with a Location header.","Use the net/http constants (http.StatusMovedPermanently, http.StatusFound) rather than raw ints.","If you don't want a redirect, use c.JSON / c.String instead of c.Redirect."],"exampleFix":"// before\nc.Redirect(http.StatusOK, \"/new\")\n// after\nc.Redirect(http.StatusFound, \"/new\")","handlingStrategy":"validation","validationCode":"func isValidRedirectCode(code int) bool {\n    return (code >= 300 && code <= 308) || code == http.StatusCreated\n}\nif !isValidRedirectCode(code) {\n    return fmt.Errorf(\"invalid redirect status %d\", code)\n}\nc.Redirect(code, url)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use http.StatusMovedPermanently / http.StatusFound / http.StatusSeeOther / http.StatusTemporaryRedirect / http.StatusPermanentRedirect.","Reserve 201 only when you really mean Created with a Location header.","Don't reach for c.Redirect for non-redirect responses — use c.JSON/c.String."],"tags":["render","redirect","http-status","panic","go"],"analyzedSha":"34dac209ffb6ef85cc78c5d217bbb7ad001d68fd","analyzedAt":"2026-08-04T21:26:18.438Z","schemaVersion":2}