gin-gonic/gin · error
catch-all wildcard '${path}' in new path '${fullPath}' confl
Error message
catch-all wildcard '${path}' in new path '${fullPath}' conflicts with existing path segment '${pathSeg}' in existing prefix '${n.path}${pathSeg}' What it means
Thrown by (*node).insertChild in tree.go:353 when a new catch-all route ('*') is being inserted under a node whose path already ends in '/' and which already has child segments. Because a catch-all would have to swallow everything after that slash, it cannot share the parent with pre-existing static or parametric children. The message names the conflicting child segment and the combined prefix so you can see what the catch-all would shadow.
Source
Thrown at tree.go:353
continue
}
// Otherwise we're done. Insert the handle in the new leaf
n.handlers = handlers
return
}
// catchAll
if i+len(wildcard) != len(path) {
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,View on GitHub (pinned to 34dac209ff)
Solutions
- Register the catch-all FIRST and the specific static children AFTER (Gin allows static children under a catch-all parent in many orderings, but the safe path is specific-before-general only when they do not share the immediate slash-parent — easiest is to test both orders).
- Move the catch-all to a distinct prefix that has no existing children, e.g. /assets/*filepath kept separate from /static/css.
- Use router.NoRoute(handler) or a middleware-based fallback instead of a catch-all route when you need a true 'match anything' behaviour without tree conflicts.
- If you genuinely need both /static/css and /static/*filepath, restructure so the catch-all parent is its own node: register /static/*filepath alone and handle /static/css inside the handler by branching on the param.
Example fix
// before
router.GET("/static/css", serveCSS)
router.GET("/static/*filepath", serveAll) // panics: conflicts with 'css'
// after — distinct prefixes, no overlap
router.GET("/static/css", serveCSS)
router.GET("/assets/*filepath", serveAll)
// or — single catch-all, branch inside the handler
router.GET("/static/*filepath", func(c *gin.Context) {
if c.Param("filepath") == "/css" { serveCSS(c); return }
serveAll(c)
}) Defensive patterns
Strategy: validation
Validate before calling
// Static catch-all conflict predictor: a '/*x' route conflicts if a sibling
// '/seg' is registered under the same parent. Maintain a registry.
type routeRegistry struct {
parentChildren map[string]map[string]bool // "/static" -> {"css": true}
}
func (r *routeRegistry) canAddCatchAll(parent, catchallParent string) error {
if kids, ok := r.parentChildren[catchallParent]; ok && len(kids) 0 {
return fmt.Errorf("catch-all under %s conflicts with existing children %v", catchallParent, keys(kids))
}
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("catch-all conflict in %s: %v", path, r)
}
}()
e.Handle(method, path, h)
return nil
} Prevention
- Prefer router.NoRoute(...) or a fallback middleware over a catch-all route when the parent already has children.
- Keep catch-alls on their own dedicated prefix (/assets/*filepath) separate from specific routes (/static/css).
- When a catch-all must coexist with specific siblings, branch on c.Param inside a single handler instead of declaring multiple routes.
- Register the catch-all first in your test builder to confirm whether the ordering resolves the conflict before relying on it in production.
When it happens
Trigger: Registering router.GET("/static/*filepath", h) AFTER router.GET("/static/css", h), or mounting a catch-all under a group that already mapped specific children such as /api/*all after /api/users and /api/orders. The catch-all is rejected because it would conflict with the existing segment 'css' (or 'users').
Common situations: Adding a catch-all / fallback route to an existing API tree; introducing router.NoRoute-style handling via a real route that overlaps already-registered children; ordering routes such that specific paths come before the wildcard.
Related errors
- '${pathSeg}' in new path '${fullPath}' conflicts with existi
- catch-all routes are only allowed at the end of the path in
- no / before catch-all in path '${fullPath}'
- handlers are already registered for path '${fullPath}'
- invalid escape string in path '${path}'
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/62c52b76b8dbe274.json.
Report an issue: GitHub.