vitessio/vitess · error
unexpected character
Error message
unexpected character %q in JSON
What it means
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.
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
Example fix
// before
out, err := json.AppendMarshalSQL(nil, []byte("{'a': NaN}"))
// after
raw := []byte(`{"a": null}`)
if !json.Valid(raw) { return err }
out, err := json.AppendMarshalSQL(nil, raw) Defensive patterns
Strategy: validation
Validate before calling
raw := []byte(input)
if !json.Valid(raw) {
return fmt.Errorf("input is not valid JSON, refusing to marshal")
} Try / catch
out, err := json.AppendMarshalSQL(nil, raw)
if err != nil {
if strings.Contains(err.Error(), "unexpected character") {
return fmt.Errorf("malformed JSON payload: %w", err)
}
return err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- expected ',' or '}' in object, got
- expected ',' or ']' in array, got
- range should be >=
- cannot marshal data
- cannot parse array value
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/f63c078fb1b3b2f7.
Report an issue: GitHub.
Appendix: source
Thrown at go/mysql/json/marshal.go:257
}
switch w.data[w.pos] {
case '{':
w.pos++
return w.writeObject(depth)
case '[':
w.pos++
return w.writeArray(depth)
case '"':
return w.writeString(top)
case 't', 'f':
return w.writeBool(top)
case 'n':
return w.writeNull(top)
default:
if w.data[w.pos] >= '0' && w.data[w.pos] <= '9' || w.data[w.pos] == '-' {
return w.writeNumber(top)
}
return fmt.Errorf("unexpected character %q in JSON", w.data[w.pos])
}
}
func (w *sqlWriter) writeObject(depth int) error {
w.buf.WriteString("JSON_OBJECT(")
first := true
for {
w.skipWhitespace()
if w.pos >= len(w.data) {
return errors.New("unexpected end of JSON input in object")
}
if w.data[w.pos] == '}' {
w.pos++
w.buf.WriteByte(')')
return nil
}
if !first {
if w.data[w.pos] != ',' {View on GitHub (pinned to 01a25a7d17)