{"record":{"id":"bb0562592d35e641","repo":"gofiber/fiber","slug":"router-route-path-cannot-be-expressed-as-a-relati","errorCode":null,"errorMessage":"router: route path cannot be expressed as a relative URL","messagePattern":"router: route path cannot be expressed as a relative URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"error.go","lineNumber":29,"sourceCode":"// Unexported because users will hopefully never need to see it.\nvar errUnreachable = errors.New(\"fiber: unreachable code, please create an issue at github.com/gofiber/fiber\")\n\n// General errors\nvar (\n\tErrGracefulTimeout = errors.New(\"shutdown: graceful timeout has been reached, exiting\")\n\t// ErrNotRunning indicates that a Shutdown method was called when the server was not running.\n\tErrNotRunning = errors.New(\"shutdown: server is not running\")\n\t// ErrHandlerExited is returned by App.Test if a handler panics or calls runtime.Goexit().\n\tErrHandlerExited = errors.New(\"runtime.Goexit() called in handler or server panic\")\n\t// ErrNoViewEngineConfigured indicates that a helper requiring a view engine was invoked without one configured.\n\tErrNoViewEngineConfigured = errors.New(\"fiber: no view engine configured\")\n\t// ErrAutoCertWithCertFile indicates AutoCertManager cannot be used with CertFile/CertKeyFile.\n\tErrAutoCertWithCertFile = errors.New(\"tls: AutoCertManager cannot be combined with CertFile/CertKeyFile\")\n\t// ErrRouteNotRepresentable indicates a route whose path no relative URL can\n\t// name, so Route.URL, GetRouteURL and Redirect().Route cannot compose one.\n\t// A path starting with two or more slashes is such a route: the URL that\n\t// would reach it opens an authority instead.\n\tErrRouteNotRepresentable = errors.New(\"router: route path cannot be expressed as a relative URL\")\n)\n\n// Fiber redirection errors\nvar (\n\tErrRedirectBackNoFallback = NewError(StatusInternalServerError, \"Referer not found, you have to enter fallback URL for redirection.\")\n)\n\n// Range errors\nvar (\n\t// ErrRangeMalformed is returned for a syntactically invalid Range header,\n\t// which RFC 9110 Section 14.2 allows a server to reject; it carries a\n\t// 400 Bad Request status so propagating it does not surface as a 500.\n\tErrRangeMalformed = NewError(StatusBadRequest, \"range: malformed range header string\")\n\t// ErrRangeUnsupported is returned for a Range header whose range unit is\n\t// not \"bytes\". RFC 9110 Section 14.2 requires an origin server to IGNORE\n\t// a Range header field with a range unit it does not understand, so\n\t// callers receiving this error should serve the full representation\n\t// instead of returning an error response. It still carries a","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/error.go#L11-L47","documentation":"ErrRouteNotRepresentable is returned by buildRouteURL (router.go:249), the shared implementation behind Route.URL, Res.GetRouteURL, and Redirect().Route(). It fires when the route's path cannot be named by any relative URL. The current check rejects paths whose normalized form differs from the stored path, or whose leading-slash count exceeds one, because two leading slashes open an authority rather than a path.","triggerScenarios":"Registering a route at a path such as \"//internal\" or \"/\\t/internal\" (which the path parser normalizes to a path with multiple leading slashes), then calling route.URL(params), c.GetRouteURL(name, params), or c.Redirect().Route(name) on it. buildRouteURL applies urlnorm.AsBrowserReads and detects the mismatch at router.go:243-248.","commonSituations":"Mounting sub-apps whose prefix accidentally introduces a double slash; constructing group prefixes with a trailing slash and routes with a leading slash; client-supplied path components concatenated without normalization; tests that assert route URL composition.","solutions":["Strip extra leading slashes from the route path before registration: strings.TrimLeft(path, \"/\") then prepend a single slash.","Audit Group and Mount prefixes for trailing slashes that combine with a leading-slash route to form \"//\".","If the double-slash is intentional, do not call URL/GetRouteURL/Redirect().Route on that route; build the URL by hand."],"exampleFix":"// before\napp.Get(\"//internal/health\", h)\nu, _ := app.GetRoute(\"//internal/health\").URL(nil)\n// after\napp.Get(\"/internal/health\", h)\nu, _ := app.GetRoute(\"/internal/health\").URL(nil)","handlingStrategy":"validation","validationCode":"// Normalize route paths and group prefixes so they never produce a\n// double leading slash.\nfunc cleanRoute(p string) string {\n    return \"/\" + strings.TrimLeft(p, \"/\")\n}\n\nfor _, r := range routes {\n    if strings.Count(cleanRoute(r), \"//\") > 0 || len(r) - len(strings.TrimLeft(r, \"/\")) > 1 {\n        log.Fatalf(\"route %q would be unrepresentable as a relative URL\", r)\n    }\n}","typeGuard":null,"tryCatchPattern":"u, err := route.URL(params)\nif err != nil {\n    if errors.Is(err, fiber.ErrRouteNotRepresentable) {\n        // rebuild the URL manually or fix the route path\n        u = \"/\" + strings.TrimLeft(route.Path, \"/\")\n    } else {\n        return err\n    }\n}","preventionTips":["Strip extra leading slashes from route paths and group prefixes before registration.","Audit Group/Mount prefixes for trailing slashes that combine with leading-slash routes.","Avoid calling URL/GetRouteURL/Redirect().Route on intentionally double-slashed paths."],"tags":["routing","url","redirect","mount","validation"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}