vitessio/vitess · error

too big depth for the nested JSON; it exceeds %d

Error message

too big depth for the nested JSON; it exceeds %d

What it means

When converting JSON text to Vitess SQL (AppendMarshalSQL path), sqlWriter.writeValue enforces a maximum nesting depth (MaxDepth). If the input JSON nests deeper than that limit, the writer aborts with this error instead of recursing unboundedly, protecting against stack exhaustion. The depth counter increments as writeValue, writeObject, and writeArray recurse into each other.

Source

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

	pos     int
	buf     *bytes2.Buffer
	scratch []byte
}

func (w *sqlWriter) skipWhitespace() {
	for w.pos < len(w.data) {
		switch w.data[w.pos] {
		case ' ', '\t', '\n', '\r':
			w.pos++
		default:
			return
		}
	}
}

func (w *sqlWriter) writeValue(top bool, depth int) error {
	if depth >= MaxDepth {
		return fmt.Errorf("too big depth for the nested JSON; it exceeds %d", MaxDepth)
	}
	w.skipWhitespace()
	if w.pos >= len(w.data) {
		return errors.New("unexpected end of JSON input")
	}
	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)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Reduce the nesting depth of the JSON input before marshaling (flatten or cap nesting at MaxDepth levels)
  2. Validate/limit nesting depth on input at the application boundary before passing it to AppendMarshalSQL
  3. If legitimate data requires deeper nesting, raise MaxDepth in go/mysql/json (accepting the larger recursion/stack cost)
  4. Reject the offending document and return a clear error to the client rather than attempting conversion

Example fix

// before
payload := strings.Repeat("[", 200) + strings.Repeat("]", 200)
out, err := json.AppendMarshalSQL(nil, []byte(payload))
// after
payload := limitNestingDepth(payload, json.MaxDepth)
out, err := json.AppendMarshalSQL(nil, []byte(payload))
Defensive patterns

Strategy: validation

Validate before calling

func depthLimited(data []byte, max int) bool {
    depth, stack := 0, []rune{}
    inStr := false
    for _, r := range string(data) {
        if inStr { if r == '\\' { continue }; if r == '"' { inStr = false }; continue }
        switch r {
        case '"': inStr = true
        case '{', '[': stack = append(stack, r); depth = max(depth, len(stack))
        case '}', ']': stack = stack[:len(stack)-1]
        }
    }
    return depth <= max
}
if !depthLimited(raw, json.MaxDepth) { return errors.New("input exceeds max JSON nesting depth") }

Try / catch

out, err := json.AppendMarshalSQL(nil, raw)
if err != nil {
    if strings.Contains(err.Error(), "too big depth") {
        return fmt.Errorf("rejecting document exceeding JSON depth limit: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling AppendMarshalSQL (or the internal writeValue/writeObject/writeArray recursion) on JSON input containing more than MaxDepth levels of nested objects/arrays, e.g. a deeply nested '[[[[[...]]]]]' payload from an untrusted source.

Common situations: Malicious or auto-generated deeply nested JSON in a SQL payload; client libraries serializing recursive data structures; fuzzing or adversarial input; accidental runaway nesting from a buggy serializer upstream.

Related errors


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