{"id":"6d7b9d4722f33c4a","repo":"labstack/echo","slug":"invalid-redirect-code-for-add-trailing-slash-middl","errorCode":null,"errorMessage":"invalid redirect code for add trailing slash middleware","messagePattern":"invalid redirect code for add trailing slash middleware","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/slash.go","lineNumber":45,"sourceCode":"//\n// Usage `Echo#Pre(AddTrailingSlash())`\nfunc AddTrailingSlash() echo.MiddlewareFunc {\n\treturn AddTrailingSlashWithConfig(AddTrailingSlashConfig{})\n}\n\n// AddTrailingSlashWithConfig returns an AddTrailingSlash middleware with config or panics on invalid configuration.\nfunc AddTrailingSlashWithConfig(config AddTrailingSlashConfig) echo.MiddlewareFunc {\n\treturn toMiddlewareOrPanic(config)\n}\n\n// ToMiddleware converts AddTrailingSlashConfig to middleware or returns an error for invalid configuration\nfunc (config AddTrailingSlashConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n\tif config.Skipper == nil {\n\t\tconfig.Skipper = DefaultSkipper\n\t}\n\tif config.RedirectCode != 0 && (config.RedirectCode < http.StatusMultipleChoices || config.RedirectCode > http.StatusPermanentRedirect) {\n\t\t// this is same check as `echo.context.Redirect()` does, but we can check this before even serving the request.\n\t\treturn nil, errors.New(\"invalid redirect code for add trailing slash middleware\")\n\t}\n\n\treturn func(next echo.HandlerFunc) echo.HandlerFunc {\n\t\treturn func(c *echo.Context) error {\n\t\t\tif config.Skipper(c) {\n\t\t\t\treturn next(c)\n\t\t\t}\n\n\t\t\treq := c.Request()\n\t\t\turl := req.URL\n\t\t\tpath := url.Path\n\t\t\tqs := c.QueryString()\n\t\t\tif !strings.HasSuffix(path, \"/\") {\n\t\t\t\tpath += \"/\"\n\t\t\t\turi := path\n\t\t\t\tif qs != \"\" {\n\t\t\t\t\turi += \"?\" + qs\n\t\t\t\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/slash.go#L27-L63","documentation":"Returned by AddTrailingSlashConfig.ToMiddleware when RedirectCode is non-zero and falls outside the valid redirect range [300, 308]. A RedirectCode of 0 is valid — it means 'rewrite internally without an HTTP redirect'. Any other value must be a 3xx status code, mirroring the check echo.Context.Redirect performs.","triggerScenarios":"Calling AddTrailingSlashWithConfig(AddTrailingSlashConfig{RedirectCode: 200}) or any code < 300 or > 308 (e.g., 301 is fine; 309, 200, 404 are not).","commonSituations":"Developer passes a status code thinking 0 means 'use default 301' (it does not — it disables the redirect); or copies a code constant that is not a 3xx (e.g., StatusOK).","solutions":["Use a 3xx code such as http.StatusMovedPermanently (301) or http.StatusPermanentRedirect (308).","If you want internal forwarding (no HTTP redirect), leave RedirectCode as 0 (the default).","Double-check the constant you pass is in the 300-308 range.","Use config.ToMiddleware() to surface the error instead of panicking."],"exampleFix":"// before (200 is not a redirect code)\nm := middleware.AddTrailingSlashWithConfig(middleware.AddTrailingSlashConfig{RedirectCode: http.StatusOK})\n// after\nm := middleware.AddTrailingSlashWithConfig(middleware.AddTrailingSlashConfig{RedirectCode: http.StatusMovedPermanently})","handlingStrategy":"validation","validationCode":"func isValidRedirectCode(code int) bool {\n    return code == 0 || (code >= 300 && code <= 308)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use a 3xx constant for RedirectCode (e.g. http.StatusMovedPermanently), or leave it 0 for internal forwarding.","Remember 0 does NOT mean 'default redirect' — it disables the HTTP redirect.","Validate the code is in [300,308] before wiring if it comes from config."],"tags":["middleware","trailing-slash","redirect","config","panic","startup"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}