gin-gonic/gin · error
invalid escape string in path '${path}'
Error message
invalid escape string in path '${path}' What it means
Thrown by findWildcard in tree.go:262 when a backslash in a route path is followed by any character other than ':'. Gin uses '\:' as an escape sequence to literally match a colon in a static path segment; any other escape (e.g. '\\', '\n', '\/' ) is invalid and the function panics during addRoute. The offending full path is included in the message.
Source
Thrown at tree.go:262
}
n.handlers = handlers
n.fullPath = fullPath
return
}
}
// Search for a wildcard segment and check the name for invalid characters.
// Returns -1 as index, if no wildcard was found.
func findWildcard(path string) (wildcard string, i int, valid bool) {
// Find start
escapeColon := false
for start, c := range []byte(path) {
if escapeColon {
escapeColon = false
if c == ':' {
continue
}
panic("invalid escape string in path '" + path + "'")
}
if c == '\\' {
escapeColon = true
continue
}
// A wildcard starts with ':' (param) or '*' (catch-all)
if c != ':' && c != '*' {
continue
}
// Find end and check for invalid characters
valid = true
for end, c := range []byte(path[start+1:]) {
switch c {
case '/':
return path[start : start+1+end], start, valid
case ':', '*':
valid = falseView on GitHub (pinned to 34dac209ff)
Solutions
- Remove every backslash from the path that is not part of an intentional '\:' escape.
- If you need a literal colon in a static segment, use the documented escape: router.GET("/users\\:id", h) matches the literal text '/users:id'.
- Build paths with path.Join or constants rather than string concatenation to avoid stray escape characters.
- Lint route strings in a test: assert none contain '\\' except in the form '\\:'.
Example fix
// before — stray backslash before a non-colon
router.GET("/files\\/static", h) // panics: '\\/' is not a valid escape
// after — plain slash, no escape needed
router.GET("/files/static", h)
// (the only valid escape is for a literal colon)
router.GET("/tag\\:literal", h) // OK, matches '/tag:literal' Defensive patterns
Strategy: validation
Validate before calling
// Reject routes containing invalid backslash escapes before registering.
var invalidEscape = regexp.MustCompile(`\\[^:]`)
func validatePath(p string) error {
if invalidEscape.MatchString(p) {
return fmt.Errorf("path %q contains an invalid backslash escape (only '\\:' is allowed)", 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("invalid path %s: %v", path, r)
}
}()
e.Handle(method, path, h)
return nil
} Prevention
- Avoid building route strings with fmt.Sprintf or concatenation; use string constants.
- Never embed Windows file paths or regexes into route definitions.
- Remember the only valid escape in a Gin path is '\\:' for a literal colon.
- Add a lint test that scans every registered path for stray backslashes.
When it happens
Trigger: Registering a path that contains a literal backslash for any reason other than escaping a colon, e.g. router.GET("/users\\:id", h) with a stray slash, or feeding a Windows-style path like "C:\\dir" into a route. Also triggered by string concatenation that introduces a '\n' or '\t' into the route literal.
Common situations: Copy-pasting a regex or Windows file path into a route definition; using fmt.Sprintf to build paths and accidentally embedding a backslash; misunderstanding the '\:' escape feature and trying to escape slashes or other characters.
Related errors
- only one wildcard per path segment is allowed, has: '${wildc
- wildcards must be named with a non-empty name in path '${ful
- catch-all routes are only allowed at the end of the path in
- no / before catch-all in path '${fullPath}'
- '${pathSeg}' in new path '${fullPath}' conflicts with existi
AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04).
Data as JSON: /data/errors/3dacc797852aa0a4.json.
Report an issue: GitHub.