{"id":"c8a1b230d4cc559c","repo":"labstack/echo","slug":"redirectconfig-is-missing-redirect-function","errorCode":null,"errorMessage":"redirectConfig is missing redirect function","messagePattern":"redirectConfig is missing redirect function","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/redirect.go","lineNumber":127,"sourceCode":"\treturn NonWWWRedirectWithConfig(RedirectNonWWWConfig)\n}\n\n// NonWWWRedirectWithConfig returns a Non-WWW redirect middleware with config or panics on invalid configuration.\nfunc NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {\n\tconfig.redirect = redirectNonWWW\n\treturn toMiddlewareOrPanic(config)\n}\n\n// ToMiddleware converts RedirectConfig to middleware or returns an error for invalid configuration\nfunc (config RedirectConfig) ToMiddleware() (echo.MiddlewareFunc, error) {\n\tif config.Skipper == nil {\n\t\tconfig.Skipper = DefaultSkipper\n\t}\n\tif config.Code == 0 {\n\t\tconfig.Code = http.StatusMovedPermanently\n\t}\n\tif config.redirect == nil {\n\t\treturn nil, errors.New(\"redirectConfig is missing redirect function\")\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, scheme := c.Request(), c.Scheme()\n\t\t\thost := req.Host\n\t\t\tif ok, url := config.redirect(scheme, host, req.RequestURI); ok {\n\t\t\t\treturn c.Redirect(config.Code, url)\n\t\t\t}\n\n\t\t\treturn next(c)\n\t\t}\n\t}, nil\n}","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/redirect.go#L109-L145","documentation":"Returned by RedirectConfig.ToMiddleware when the unexported config.redirect function is nil. That function implements the specific redirect decision (HTTPS, WWW, etc.) and is set by the preset constructors like HTTPSRedirectWithConfig; a bare RedirectConfig{} has no redirect logic. Because the field is unexported, you cannot set it yourself — you must use a preset or one of the WithConfig helpers.","triggerScenarios":"Constructing RedirectConfig{} and passing it to toMiddlewareOrPanic or its ToMiddleware directly, instead of going through HTTPSRedirectWithConfig / WWWRedirectWithConfig / etc. Also reachable if you copy a preset config and zero out its redirect logic via reflection or by reassigning the whole struct.","commonSituations":"Developer wants a custom Code and builds RedirectConfig{Code: 301} manually instead of starting from RedirectHTTPSConfig; or is unaware that redirect logic is bound by calling the specific WithConfig constructor.","solutions":["Start from a preset, e.g. HTTPSRedirectWithConfig(RedirectHTTPSConfig) which sets redirect=redirectHTTPS.","To customize the status code, copy a preset and change only Code: cfg := RedirectHTTPSConfig; cfg.Code = http.StatusMovedPermanently; HTTPSRedirectWithConfig(cfg).","Pick the constructor matching your goal: HTTPSRedirect, HTTPSWWWRedirect, HTTPSNonWWWRedirect, WWWRedirect, NonWWWRedirect (each has a WithConfig variant).","Do not hand-construct RedirectConfig{} expecting redirect logic — the field cannot be set externally."],"exampleFix":"// before (will panic: redirect is nil)\nm := toMiddlewareOrPanic(middleware.RedirectConfig{Code: 301})\n// after\ncfg := middleware.RedirectHTTPSConfig\ncfg.Code = http.StatusMovedPermanently\nm := middleware.HTTPSRedirectWithConfig(cfg)","handlingStrategy":"validation","validationCode":"// Always start from a preset; never hand-construct RedirectConfig{}.\nfunc httpsRedirectMiddleware(code int) (echo.MiddlewareFunc, error) {\n    if code != 0 && (code < 300 || code > 308) {\n        return nil, errors.New(\"redirect code must be a 3xx\")\n    }\n    cfg := middleware.RedirectHTTPSConfig\n    cfg.Code = code\n    return cfg.ToMiddleware()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always start from a preset config (RedirectHTTPSConfig, RedirectWWWConfig, etc.) — the redirect field is unexported and only the preset constructors set it.","To customise the status code, copy a preset and change only Code.","Never build RedirectConfig{} from scratch expecting redirect logic; the field cannot be set externally."],"tags":["middleware","redirect","config","panic","startup"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}