labstack/echo · error

invalid redirect code for remove trailing slash middleware

Error message

invalid redirect code for remove trailing slash middleware

What it means

Returned by RemoveTrailingSlashConfig.ToMiddleware when RedirectCode is non-zero and outside [300, 308]. Identical guard to AddTrailingSlash: 0 means internal rewrite, any other value must be a 3xx redirect status.

Source

Thrown at middleware/slash.go:109

//
// Usage `Echo#Pre(RemoveTrailingSlash())`
func RemoveTrailingSlash() echo.MiddlewareFunc {
	return RemoveTrailingSlashWithConfig(RemoveTrailingSlashConfig{})
}

// RemoveTrailingSlashWithConfig returns a RemoveTrailingSlash middleware with config or panics on invalid configuration.
func RemoveTrailingSlashWithConfig(config RemoveTrailingSlashConfig) echo.MiddlewareFunc {
	return toMiddlewareOrPanic(config)
}

// ToMiddleware converts RemoveTrailingSlashConfig to middleware or returns an error for invalid configuration
func (config RemoveTrailingSlashConfig) ToMiddleware() (echo.MiddlewareFunc, error) {
	if config.Skipper == nil {
		config.Skipper = DefaultSkipper
	}
	if config.RedirectCode != 0 && (config.RedirectCode < http.StatusMultipleChoices || config.RedirectCode > http.StatusPermanentRedirect) {
		// this is same check as `echo.context.Redirect()` does, but we can check this before even serving the request.
		return nil, errors.New("invalid redirect code for remove trailing slash middleware")
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {
		return func(c *echo.Context) error {
			if config.Skipper(c) {
				return next(c)
			}

			req := c.Request()
			url := req.URL
			path := url.Path
			qs := c.QueryString()
			l := len(path) - 1
			if l > 0 && strings.HasSuffix(path, "/") {
				path = path[:l]
				uri := path
				if qs != "" {
					uri += "?" + qs

View on GitHub (pinned to 05489dc173)

Solutions

  1. Use a 3xx code such as http.StatusMovedPermanently (301).
  2. Leave RedirectCode at 0 if you want the path rewritten internally without an HTTP redirect.
  3. Validate the constant is within 300-308 before wiring.
  4. Use config.ToMiddleware() to receive the error rather than a panic.

Example fix

// before
m := middleware.RemoveTrailingSlashWithConfig(middleware.RemoveTrailingSlashConfig{RedirectCode: http.StatusFound})
// after (or omit RedirectCode for internal forward)
m := middleware.RemoveTrailingSlashWithConfig(middleware.RemoveTrailingSlashConfig{RedirectCode: http.StatusMovedPermanently})
Defensive patterns

Strategy: validation

Validate before calling

func isValidRedirectCode(code int) bool {
    return code == 0 || (code >= 300 && code <= 308)
}

Prevention

When it happens

Trigger: Calling RemoveTrailingSlashWithConfig(RemoveTrailingSlashConfig{RedirectCode: 301}) is fine; passing 200, 309, 404, etc. triggers the error.

Common situations: Developer passes http.StatusOK or a non-redirect constant; or confuses RedirectCode=0 (internal forward) with 'use default redirect'.

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/29bd1dd346e8e6c3.json. Report an issue: GitHub.