gin-gonic/gin · error

invalid escape string in 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.

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: /api/errors/3dacc797852aa0a4. Report an issue: GitHub.

Appendix: 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)