{"record":{"id":"c8ce3653dd618957","repo":"antonmedv/fx","slug":"expected-colon-after-object-key-got-q","errorCode":null,"errorMessage":"Expected colon after object key, got %q","messagePattern":"Expected colon after object key, got %q","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/jsonx/json.go","lineNumber":345,"sourceCode":"\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--\n\n\t\tobject.Append(value)\n\t\tobject.Size += 1\n\n\t\tp.skipWhitespace()\n\n\t\tcommaPos := p.end\n\t\tif p.char == ',' {\n\t\t\tobject.End.Comma = true","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/antonmedv/fx/blob/4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe/internal/jsonx/json.go#L327-L363","documentation":"After scanning an object key string, the parser requires a ':' separating the key from its value. If the next non-whitespace character is not ':', it panics with this message showing the actual character found. This enforces the JSON object grammar key:value pair structure.","triggerScenarios":"Parsing {\"a\" 1} (colon omitted), {\"a\"; 1}, {\"a\" \"b\"}, or key followed immediately by '}' e.g. {\"a\"}.","commonSituations":"Typo'd separators in hand-edited JSON; JSON written from another language's map/string syntax; regex-generated JSON with wrong join characters; truncation cutting off the ':value' part.","solutions":["Insert the missing colon: {\"a\" 1} -> {\"a\": 1}","Remove the extra key if the value was accidentally deleted ({\"a\"} -> {} or {\"a\": null})","Check for wrong separator characters like ';' or '=' and replace with ':'","Run the input through a JSON validator to locate the exact position"],"exampleFix":"// before\n{\"name\": \"x\", \"enabled\" true}\n\n// after\n{\"name\": \"x\", \"enabled\": true}","handlingStrategy":"validation","validationCode":"func validateColonSeparators(src string) error {\n\t// ensure every top-level key string inside an object is followed by ':'\n\tdepth := 0; inStr := false; expectColon := false\n\tfor i := 0; i < len(src); i++ {\n\t\tc := src[i]\n\t\tif inStr { if c == '\\\\' { i++ } else if c == '\"' { inStr = false; if depth > 0 { expectColon = true } }; continue }\n\t\tswitch c {\n\t\tcase '\"': inStr = true\n\t\tcase '{': depth++\n\t\tcase '}': depth--\n\t\tcase ':': expectColon = false\n\t\tcase ',', '{': if expectColon { return fmt.Errorf(\"missing ':' at offset %d\", i) }\n\t\t}\n\t\tif expectColon && c != ':' && c != ' ' && c != '\\t' && c != '\\n' && c != '\\r' {\n\t\t\treturn fmt.Errorf(\"expected ':' at offset %d, got %q\", i, c)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"func 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 (missing colon?): %v\", r)\n\t\t}\n\t}()\n\troot = p.Parse(data)\n\treturn\n}","preventionTips":["Use a serializer for generating JSON; never build objects with sprintf","Lint JSON configs in CI before they reach runtime","Check for regional keyboard mistakes (':' vs ';') in hand-edited files","When truncating JSON streams, re-validate the remainder before parsing"],"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"}