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 = false

View on GitHub (pinned to 34dac209ff)

Solutions

  1. Remove every backslash from the path that is not part of an intentional '\:' escape.
  2. 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'.
  3. Build paths with path.Join or constants rather than string concatenation to avoid stray escape characters.
  4. 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

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


AI-assisted analysis of gin-gonic/gin@34dac209ff (2026-08-04). Data as JSON: /data/errors/3dacc797852aa0a4.json. Report an issue: GitHub.