vitessio/vitess · error

reading JSON object key: %w

Error message

reading JSON object key: %w

What it means

This error wraps a failure that occurred while reading the string key of a JSON object during conversion of a raw JSON document into a MySQL SQL expression (JSON_OBJECT). The writeObject parser requires every object key to be a double-quoted JSON string, and writeStringContent (which reads and SQL-encodes that key) returned an error — e.g. the key string is unterminated, or contains a malformed escape sequence. The wrapper adds context so the caller knows the failure happened in the key portion of an object rather than in a value.

Source

Thrown at go/mysql/json/marshal.go:290

			return nil
		}
		if !first {
			if w.data[w.pos] != ',' {
				return fmt.Errorf("expected ',' or '}' in object, got %q", w.data[w.pos])
			}
			w.pos++
			w.buf.WriteString(", ")
			w.skipWhitespace()
		}
		first = false

		// Key (always a string).
		if w.pos >= len(w.data) || w.data[w.pos] != '"' {
			return errors.New("expected string key in JSON object")
		}
		w.buf.WriteString("_utf8mb4")
		if err := w.writeStringContent(); err != nil {
			return fmt.Errorf("reading JSON object key: %w", err)
		}
		w.buf.WriteString(", ")

		// Colon separator.
		w.skipWhitespace()
		if w.pos >= len(w.data) || w.data[w.pos] != ':' {
			return errors.New("expected ':' after object key")
		}
		w.pos++

		// Value.
		if err := w.writeValue(false, depth+1); err != nil {
			return err
		}
	}
}

func (w *sqlWriter) writeArray(depth int) error {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Validate the JSON with encoding/json Unmarshal (or json.Valid) before passing it to the writer, so malformed keys are rejected with a standard parser error.
  2. Locate the object key at the reported position and fix or re-encode the JSON with a proper encoder (json.Marshal), which guarantees well-formed key strings and escapes.
  3. If input comes from an untrusted/external source, check for truncation (complete document received) and reject payloads that fail json.Valid with a clear client-side error.
  4. If the invalid escape comes from double-escaping (e.g. \"\\\\q\" produced by string escaping in another layer), remove the extra escaping layer in the producer.

Example fix

// before: hand-built JSON with invalid escape
payload := fmt.Sprintf(`{"na\\qme": %d}`, id)
// after: build JSON with the encoder
b, _ := json.Marshal(map[string]int{"name": id})
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid(input) {
	return fmt.Errorf("invalid JSON document: object key not readable")
}

Try / catch

if err := writeJSONAsSQL(input); err != nil {
	var pe *json.SyntaxError
	if errors.As(err, nil) || strings.Contains(err.Error(), "reading JSON object key") {
		// fall back: reject or re-encode the document
		return handleInvalidJSON(input, err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling the JSON-to-SQL writer (sqlWriter/writeValue path, e.g. via marshaling a JSON column value into JSON_OBJECT(...) SQL) with a document whose object key string is malformed: an unterminated key string (no closing quote before end of input), a key containing an invalid escape character (e.g. {"a\q": 1}), or a key with a truncated/invalid \u escape (e.g. {"\u12": 1}). Also triggered when the key string is truncated by a length-limited or corrupt input buffer.

Common situations: Applications storing hand-built JSON strings in a Vitess/MySQL JSON column where the JSON was assembled by string concatenation instead of a JSON encoder; corrupted JSON payloads arriving over the wire or read from a damaged binlog/audit log; truncation of a large JSON document by an intermediate layer (column size limits, log line cuts) leaving a key string open.

Related errors


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