vitessio/vitess · error

unexpected character %q in JSON

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.

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)

Solutions

  1. Validate the JSON input with encoding/json.Valid (or equivalent) before calling AppendMarshalSQL
  2. Replace invalid literals (NaN, Infinity, undefined) with valid JSON values (null, quoted strings, numbers)
  3. Fix quoting: JSON strings must use double quotes, not single quotes
  4. 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

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


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/f63c078fb1b3b2f7. Report an issue: GitHub.