antonmedv/fx · error

Invalid escape sequence '\%c'

Error message

Invalid escape sequence '\%c'

What it means

In strict mode, scanString encountered a backslash escape whose following character is not one of the JSON-legal escapes (" \ / b f n r t u). The library rejects the document because such escapes are invalid JSON.

Source

Thrown at internal/jsonx/json.go:231

			escaped = false
			if p.strict {
				switch p.char {
				case 'u':
					var s string
					for i := 0; i < 4; i++ {
						p.next()
						if !utils.IsHexDigit(p.char) {
							panic(fmt.Sprintf("Invalid Unicode escape sequence '\\u%s%c'", s, p.char))
						}
						s += string(p.char)
					}
					_, err := strconv.ParseInt(s, 16, 32)
					if err != nil {
						panic(fmt.Sprintf("Invalid Unicode escape sequence '\\u%s'", s))
					}
				case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
				default:
					panic(fmt.Sprintf("Invalid escape sequence '\\%c'", p.char))
				}
			}
		} else if p.char == '\\' {
			escaped = true
		} else if p.char == '"' {
			break
		} else if p.char == 0 {
			panic("Unexpected end of input in string")
		} else if rune(p.char) > unicode.MaxRune {
			panic(fmt.Sprintf("Invalid character code point %d in string", p.char))
		}
		p.next()
	}

	str := string(p.data[start:p.end])
	p.next()

	return str

View on GitHub (pinned to 4f31cd3a0c)

Solutions

  1. Double the backslashes in the input ("C:\\Users\\name") or use forward slashes
  2. Remove the invalid escape or replace it with the correct one (\n for newline, \t for tab, etc.)
  3. Serialize the string with encoding/json Marshal instead of concatenating it manually
  4. Disable strict mode if you control the parser options and only need lenient scanning (escapes then pass through unvalidated)

Example fix

// before
{"path": "C:\temp\file"}
// after
{"path": "C:\\temp\\file"}
Defensive patterns

Strategy: validation

Validate before calling

// Reject invalid JSON escapes before parsing
valid := `"\\/bfnrtu`
s := string(b)
for i := 0; i < len(s); i++ {
	if s[i] == '\\' && i+1 < len(s) && !strings.ContainsRune(valid, rune(s[i+1])) {
		return fmt.Errorf("invalid escape at offset %d", i)
	}
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		if msg, ok := r.(string); ok && strings.Contains(msg, "Invalid escape sequence") {
			err = errors.New("string contains a non-JSON backslash escape")
		}
	}
}()

Prevention

When it happens

Trigger: Parsing a string like "bad \x41 escape" or "C:\temp\new" with strict parsing enabled; single-quoted or template strings pasted into JSON; Windows paths embedded without doubling backslashes.

Common situations: Windows file paths in config files ("C:\Users\name"), regex patterns copied unescaped, hand-written JSON where \a or \x was used, shell-generated JSON with improper quoting.

Related errors


AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02). Data as JSON: /api/errors/9981f36224d9c578. Report an issue: GitHub.