antonmedv/fx · error
Expected object key to be a string, got %q
Error message
Expected object key to be a string, got %q
What it means
This error is thrown by the JSON parser while parsing an object: after '{' or a comma, it expects the next token to be a quoted string serving as the object key. If the current character is anything other than '"', the parser panics with this message, echoing the offending character. It fires because JSON grammar only permits string keys in objects.
Source
Thrown at internal/jsonx/json.go:336
Depth: p.depth,
LineNumber: p.lineNumberPlusPlus(),
}
object.Value = curlyBracketOpen
p.next()
p.skipWhitespace()
// Empty object
if p.char == '}' {
object.Value = curlyBracketPair
p.next()
return object
}
for {
// Expecting a key which should be a string
if p.char != '"' {
panic(fmt.Sprintf("Expected object key to be a string, got %q", p.char))
}
keyBytes := p.scanString()
p.skipWhitespace()
// Expecting colon after key
if p.char != ':' {
panic(fmt.Sprintf("Expected colon after object key, got %q", p.char))
}
p.next()
p.depth++
value := p.parseValue(false)
value.Key = keyBytes
value.Parent = object
p.depth--View on GitHub (pinned to 4f31cd3a0c)
Solutions
- Quote the object key with double quotes: {foo:1} -> {"foo":1}
- Replace single quotes with double quotes: {'a':1} -> {"a":1}
- Remove stray commas or characters before the key (e.g. {,} -> {})
- Validate the JSON with a linter/formatter (jq, JSONLint) before feeding it to the parser
Example fix
// before
{"name": "x", "enabled": true}
// given input: {name: "x"}
// after
{"name": "x"} Defensive patterns
Strategy: validation
Validate before calling
func validateObjectKeys(src string) error {
// reject unquoted keys before parsing: look for '{' or ',' followed by non-'"', non-'}' content
inStr := false
for i := 0; i < len(src); i++ {
c := src[i]
if c == '"' { inStr = !inStr; continue }
if inStr { continue }
if c == '{' || c == ',' {
j := i + 1
for j < len(src) && (src[j]==' '||src[j]=='\t'||src[j]=='\n'||src[j]=='\r') { j++ }
if j < len(src) && src[j] != '"' && src[j] != '}' {
return fmt.Errorf("object key at offset %d must be a quoted string, got %q", j, src[j])
}
}
}
return nil
} Try / catch
// the library panics; recover at the API boundary
func safeParse(p *jsonx.JsonParser, data []byte) (root *jsonx.Node, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("json parse failed: %v", r)
}
}()
root = p.Parse(data)
return
} Prevention
- Always emit JSON via a serializer instead of string concatenation
- Run json.Unmarshal or jq as a pre-flight validator on untrusted input
- Never hand-quote keys with single quotes; JSON requires double quotes
- Add a pre-commit/lint check for JSON files in config directories
When it happens
Trigger: Parsing input like {foo:1} (unquoted key), {foo,:1}, {,}, {'a':1} (single quotes), or a truncated object where the key is missing entirely (e.g. '{' followed by end-of-input or whitespace then a non-quote char).
Common situations: Hand-written JSON config files with JavaScript-style unquoted keys; single-quoted keys copied from JS objects; template-generated JSON with missing placeholders; concatenation or truncation bugs producing partial JSON.
Related errors
- Expected colon after object key, got %q
- Unexpected character %q in object
- Invalid character %q in array
- Invalid escape sequence '\%c'
- Invalid character %q in number
AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02).
Data as JSON: /api/errors/d6a34c64e4cfffd5.
Report an issue: GitHub.