vitessio/vitess · warning

err.Error() (JSON marshal failure)

Error message

err.Error() (JSON marshal failure)

What it means

This is the HTTP 500 returned by the /twopcz handler when json.Marshal of the in-flight distributed transaction report (Distributed, Prepared, Failed lists) fails. In practice this is rare — it means the tx structures could not be serialized, typically due to an in-memory data anomaly rather than user input. The raw err.Error() text is written as the response body.

Source

Thrown at go/vt/vttablet/tabletserver/twopcz.go:175

	}
	distributed, prepared, failed, err := txe.ReadTwopcInflight()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	format := r.FormValue("format")
	if format == "json" {
		w.Header().Set("Content-Type", "application/json")
		js, err := json.Marshal(struct {
			Distributed      []*tx.DistributedTx
			Prepared, Failed []*tx.PreparedTx
		}{
			Distributed: distributed,
			Prepared:    prepared,
			Failed:      failed,
		})
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(js)
		return
	}

	w.Write(gridTable)
	w.Write([]byte("<h2>WARNING: Actions on this page can jeopardize data integrity.</h2>\n"))
	if msg != "" {
		fmt.Fprintln(w, html.EscapeString(msg))
	}

	w.Write(startTable)
	w.Write(failedzHeader)
	for _, row := range failed {
		if err := failedzRow.Execute(w, row); err != nil {
			log.Error(fmt.Sprintf("queryz: couldn't execute template: %v", err))

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Read the raw error in the 500 body; it names the marshal failure and the offending type/field.
  2. Retry the request — transient in-memory anomalies are usually resolved by a fresh read.
  3. Use the HTML format (omit format=json) to view the same data and confirm whether it is a serialization-only issue.
  4. If reproducible, capture the error and the offending dtid and file an issue; restart vttablet to reset in-memory transaction state if it is wedged.
Defensive patterns

Strategy: fallback

Validate before calling

// Fall back to HTML format when JSON rendering of 2PC data fails
url := tabletURL + "/twopcz?format=json"
if lastJSONFailed {
    url = tabletURL + "/twopcz"
}

Try / catch

resp, err := http.Get(tabletURL + "/twopcz?format=json")
if resp.StatusCode == http.StatusInternalServerError {
    // retry once with HTML format
    resp, err = http.Get(tabletURL + "/twopcz")
}

Prevention

When it happens

Trigger: A request to /twopcz?format=json where json.Marshal of the []*tx.DistributedTx / []*tx.PreparedTx payload returns an error, e.g. the transaction store contains data that cannot be marshaled (unsupported/corrupt field values in the tx structs).

Common situations: Scripting /twopcz?format=json to collect 2PC state for automation and getting a 500 back; running against a build/version where the tx protobuf structures changed; extremely unusual in-memory state after a crash.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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