{"record":{"id":"f63c078fb1b3b2f7","repo":"vitessio/vitess","slug":"unexpected-character-q-in-json","errorCode":null,"errorMessage":"unexpected character %q in JSON","messagePattern":"unexpected character %q in JSON","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/json/marshal.go","lineNumber":257,"sourceCode":"\t}\n\tswitch w.data[w.pos] {\n\tcase '{':\n\t\tw.pos++\n\t\treturn w.writeObject(depth)\n\tcase '[':\n\t\tw.pos++\n\t\treturn w.writeArray(depth)\n\tcase '\"':\n\t\treturn w.writeString(top)\n\tcase 't', 'f':\n\t\treturn w.writeBool(top)\n\tcase 'n':\n\t\treturn w.writeNull(top)\n\tdefault:\n\t\tif w.data[w.pos] >= '0' && w.data[w.pos] <= '9' || w.data[w.pos] == '-' {\n\t\t\treturn w.writeNumber(top)\n\t\t}\n\t\treturn fmt.Errorf(\"unexpected character %q in JSON\", w.data[w.pos])\n\t}\n}\n\nfunc (w *sqlWriter) writeObject(depth int) error {\n\tw.buf.WriteString(\"JSON_OBJECT(\")\n\tfirst := true\n\tfor {\n\t\tw.skipWhitespace()\n\t\tif w.pos >= len(w.data) {\n\t\t\treturn errors.New(\"unexpected end of JSON input in object\")\n\t\t}\n\t\tif w.data[w.pos] == '}' {\n\t\t\tw.pos++\n\t\t\tw.buf.WriteByte(')')\n\t\t\treturn nil\n\t\t}\n\t\tif !first {\n\t\t\tif w.data[w.pos] != ',' {","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/json/marshal.go#L239-L275","documentation":"sqlWriter.writeValue dispatches on the current byte of the JSON input; after handling '{', '[', '\"', 't'/'f'/'n' and digits/'-', any other character is not valid at that position in a JSON document, so the writer returns this error. It means the input being converted to SQL via AppendMarshalSQL is malformed JSON or contains an unexpected literal character.","triggerScenarios":"Calling AppendMarshalSQL with input where writeValue encounters a byte that is not an object start, array start, quote, true/false/null prefix, digit, or '-': e.g. single-quoted strings (')'abc''), bare words, trailing garbage like 'undefined', NaN/Infinity literals, or a string not properly closed.","commonSituations":"Building JSON by string concatenation with unquoted values; JavaScript-specific literals (undefined, NaN, Infinity) leaking into SQL payloads; single quotes from another serialization format; a broken upstream encoder emitting partial JSON.","solutions":["Validate the JSON input with encoding/json.Valid (or equivalent) before calling AppendMarshalSQL","Replace invalid literals (NaN, Infinity, undefined) with valid JSON values (null, quoted strings, numbers)","Fix quoting: JSON strings must use double quotes, not single quotes","Fix the upstream producer/serializer that emitted the malformed byte"],"exampleFix":"// before\nout, err := json.AppendMarshalSQL(nil, []byte(\"{'a': NaN}\"))\n// after\nraw := []byte(`{\"a\": null}`)\nif !json.Valid(raw) { return err }\nout, err := json.AppendMarshalSQL(nil, raw)","handlingStrategy":"validation","validationCode":"raw := []byte(input)\nif !json.Valid(raw) {\n    return fmt.Errorf(\"input is not valid JSON, refusing to marshal\")\n}","typeGuard":null,"tryCatchPattern":"out, err := json.AppendMarshalSQL(nil, raw)\nif err != nil {\n    if strings.Contains(err.Error(), \"unexpected character\") {\n        return fmt.Errorf(\"malformed JSON payload: %w\", err)\n    }\n    return err\n}","preventionTips":["Always validate with encoding/json.Valid before AppendMarshalSQL","Replace JS-only literals (NaN, Infinity, undefined) with valid JSON equivalents at the producer","Use double quotes for all JSON strings; never hand-concatenate JSON","Log the offending byte position/context to identify the bad producer quickly"],"tags":["go","json","parsing","syntax-error"],"backgroundTag":"malformed-json-input","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}