gin-gonic/gin · error
no / before catch-all in path '${fullPath}'
Error message
no / before catch-all in path '${fullPath}' What it means
Thrown by (*node).insertChild in tree.go:363 during catch-all insertion when the byte immediately before the '*' marker is not '/'. Gin models a catch-all as a two-node structure: a parent node ending in '/' and a child holding '/*name'. If the path lacks the slash (e.g. /files*name or /foo*bar) the parent cannot be split and the tree rejects the route.
Source
Thrown at tree.go:363
panic("catch-all routes are only allowed at the end of the path in path '" + fullPath + "'")
}
if len(n.path) > 0 && n.path[len(n.path)-1] == '/' {
pathSeg := ""
if len(n.children) != 0 {
pathSeg, _, _ = strings.Cut(n.children[0].path, "/")
}
panic("catch-all wildcard '" + path +
"' in new path '" + fullPath +
"' conflicts with existing path segment '" + pathSeg +
"' in existing prefix '" + n.path + pathSeg +
"'")
}
// currently fixed width 1 for '/'
i--
if i < 0 || path[i] != '/' {
panic("no / before catch-all in path '" + fullPath + "'")
}
n.path = path[:i]
// First node: catchAll node with empty path
child := &node{
wildChild: true,
nType: catchAll,
fullPath: fullPath,
}
n.addChild(child)
n.indices = "/"
n = child
n.priority++
// second node: node holding the variable
child = &node{View on GitHub (pinned to 34dac209ff)
Solutions
- Insert a '/' before the '*': /files/*filepath instead of /files*filepath.
- When concatenating a base path and a catch-all, ensure the join introduces exactly one slash: path.Join(base, "/*filepath") or assert the boundary explicitly.
- Lint routes with a regex that forbids a non-'/' byte directly preceding '*'.
Example fix
// before
router.GET("/files*filepath", h) // panics: no '/' before '*'
// after
router.GET("/files/*filepath", h) Defensive patterns
Strategy: validation
Validate before calling
// Reject catch-all markers not preceded by '/'.
var badCatchAll = regexp.MustCompile(`[^/]\*`)
func validateCatchAllSlash(p string) error {
if badCatchAll.MatchString(p) {
return fmt.Errorf("path %q: '*' must be preceded by '/'", p)
}
return nil
} Try / catch
func safeRegister(e *gin.Engine, method, path string, h gin.HandlerFunc) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("missing slash before catch-all in %s: %v", path, r)
}
}()
e.Handle(method, path, h)
return nil
} Prevention
- Always write catch-alls as '/*name', never '*name' glued to the previous segment.
- When joining a base path with a catch-all, use path.Join and verify the slash boundary.
- Lint every route for the regex /[^/]\*/.
When it happens
Trigger: Registering /files*filepath, /download*archive, or any catch-all written without the separating slash. Also triggered by path manipulation that strips the slash, e.g. strings.TrimSuffix(basePath, "/") + "*all".
Common situations: Typing a catch-all quickly and omitting the slash; building paths programmatically and forgetting the delimiter; copy-pasting a param-style segment (':') and converting only the marker to '*' without adding the slash.
Related errors
- catch-all routes are only allowed at the end of the path in
- invalid escape string in path '${path}'
- only one wildcard per path segment is allowed, has: '${wildc
- wildcards must be named with a non-empty name in path '${ful
- catch-all wildcard '${path}' in new path '${fullPath}' confl
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/177b63afe3820c0f.json.
Report an issue: GitHub.