{"record":{"id":"d6a34c64e4cfffd5","repo":"antonmedv/fx","slug":"expected-object-key-to-be-a-string-got-q","errorCode":null,"errorMessage":"Expected object key to be a string, got %q","messagePattern":"Expected object key to be a string, got %q","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/jsonx/json.go","lineNumber":336,"sourceCode":"\t\tDepth:      p.depth,\n\t\tLineNumber: p.lineNumberPlusPlus(),\n\t}\n\tobject.Value = curlyBracketOpen\n\n\tp.next()\n\tp.skipWhitespace()\n\n\t// Empty object\n\tif p.char == '}' {\n\t\tobject.Value = curlyBracketPair\n\t\tp.next()\n\t\treturn object\n\t}\n\n\tfor {\n\t\t// Expecting a key which should be a string\n\t\tif p.char != '\"' {\n\t\t\tpanic(fmt.Sprintf(\"Expected object key to be a string, got %q\", p.char))\n\t\t}\n\n\t\tkeyBytes := p.scanString()\n\n\t\tp.skipWhitespace()\n\n\t\t// Expecting colon after key\n\t\tif p.char != ':' {\n\t\t\tpanic(fmt.Sprintf(\"Expected colon after object key, got %q\", p.char))\n\t\t}\n\n\t\tp.next()\n\n\t\tp.depth++\n\t\tvalue := p.parseValue(false)\n\t\tvalue.Key = keyBytes\n\t\tvalue.Parent = object\n\t\tp.depth--","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/antonmedv/fx/blob/4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe/internal/jsonx/json.go#L318-L354","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\n{\"name\": \"x\", \"enabled\": true}\n// given input: {name: \"x\"}\n\n// after\n{\"name\": \"x\"}","handlingStrategy":"validation","validationCode":"func validateObjectKeys(src string) error {\n\t// reject unquoted keys before parsing: look for '{' or ',' followed by non-'\"', non-'}' content\n\tinStr := false\n\tfor i := 0; i < len(src); i++ {\n\t\tc := src[i]\n\t\tif c == '\"' { inStr = !inStr; continue }\n\t\tif inStr { continue }\n\t\tif c == '{' || c == ',' {\n\t\t\tj := i + 1\n\t\t\tfor j < len(src) && (src[j]==' '||src[j]=='\\t'||src[j]=='\\n'||src[j]=='\\r') { j++ }\n\t\t\tif j < len(src) && src[j] != '\"' && src[j] != '}' {\n\t\t\t\treturn fmt.Errorf(\"object key at offset %d must be a quoted string, got %q\", j, src[j])\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"// the library panics; recover at the API boundary\nfunc safeParse(p *jsonx.JsonParser, data []byte) (root *jsonx.Node, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"json parse failed: %v\", r)\n\t\t}\n\t}()\n\troot = p.Parse(data)\n\treturn\n}","preventionTips":["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"],"tags":["json","parser","syntax-error"],"backgroundTag":"invalid-json-syntax","analyzedSha":"4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe","analyzedAt":"2026-09-02T02:17:47.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}