antonmedv/fx · error
Unexpected character %q in keyword
Error message
Unexpected character %q in keyword
What it means
parseKeyword matches literal keywords (true, false, null) character by character. If the character at position i does not match the expected letter of the keyword, the parser panics with "Unexpected character %q in keyword". This detects misspelled or truncated keywords like tru, nul, or falsy. The source region shows this fires inside the matching loop when p.char != name[i].
Source
Thrown at internal/jsonx/json.go:462
}
closeBracket.Value = squareBracketClose
closeBracket.Parent = arr
closeBracket.Index = -1
arr.Append(closeBracket)
p.next()
return arr
}
panic(fmt.Sprintf("Invalid character %q in array", p.char))
}
}
func (p *JsonParser) parseKeyword(name string, kind Kind) *Node {
start := p.end - 1
for i := 1; i < len(name); i++ {
p.next()
if p.char != name[i] {
panic(fmt.Sprintf("Unexpected character %q in keyword", p.char))
}
}
p.next()
if isEndOfValue(p.char) {
keyword := &Node{
Kind: kind,
Depth: p.depth,
Value: string(p.data[start : p.end-1]),
LineNumber: p.lineNumberPlusPlus(),
}
return keyword
}
panic(fmt.Sprintf("Unexpected character %q in keyword", p.char))
}
func (p *JsonParser) parseNullOrNan() *Node {
p.next()View on GitHub (pinned to 4f31cd3a0c)
Solutions
- Spell the keyword exactly lowercase: true, false, null (not True, tru, Null)
- Fix case-sensitivity errors (True -> true)
- If a boolean/string was intended, quote non-keyword values: "True"
- Validate with a JSON linter before parsing
Example fix
// before
{"enabled": True}
// after
{"enabled": true} Defensive patterns
Strategy: validation
Validate before calling
func validateKeywords(src string) error {
// reject non-lowercase or misspelled literals outside strings
tokens := []string{"true", "false", "null"}
re := regexp.MustCompile(`(?<!["\w])([TtFfNn][A-Za-z]*)`)
inStr := false
for i := 0; i < len(src); i++ {
if src[i] == '"' { inStr = !inStr; continue }
if inStr { continue }
rest := src[i:]
loc := re.FindStringIndex(rest)
if loc != nil && loc[0] == 0 {
word := rest[loc[0]:loc[1]]
ok := false
for _, t := range tokens { if word == t { ok = true } }
if !ok { return fmt.Errorf("invalid literal %q at offset %d (use lowercase true/false/null)", word, i) }
i += loc[1] - 1
}
}
return nil
} Try / catch
func safeParse(p *jsonx.JsonParser, data []byte) (root *jsonx.Node, err error) {
defer func() {
if r := recover(); r != nil {
if strings.Contains(fmt.Sprint(r), "in keyword") {
err = fmt.Errorf("misspelled literal keyword: %v", r)
return
}
err = fmt.Errorf("json parse failed: %v", r)
}
}()
root = p.Parse(data)
return
} Prevention
- JSON literals are lowercase — never write True/False/Null/TRUE
- Search configs for common typos (tru, flase, nul) with grep before deployment
- Quote non-keyword words as strings if that was the intent
- Run a JSON linter as a pre-commit hook
When it happens
Trigger: Parsing inputs such as tru, treu, nul1, fals, or nullx's first mismatch char, e.g. 't' followed by anything other than 'r', entered parseKeyword via parseValue; also NaN handled separately in non-strict mode.
Common situations: Hand-edited JSON with typos in true/false/null; case mismatches like True/TRUE (JSON is case-sensitive); template glitches producing partial keywords; OCR or transcription errors in config.
Related errors
- Expected object key to be a string, got %q
- Expected colon after object key, got %q
- Unexpected character %q in object
- Invalid character %q in array
- Unexpected end of input in comment
AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02).
Data as JSON: /api/errors/47e966043a2cde00.
Report an issue: GitHub.