vitessio/vitess · error

err.Error() (ReadTwopcInflight failure)

Error message

err.Error() (ReadTwopcInflight failure)

What it means

This is the HTTP 500 returned by the /twopcz debug UI handler when txe.ReadTwopcInflight() fails to enumerate in-flight distributed transactions. ReadTwopcInflight queries the underlying transaction store (and MySQL) for unresolved prepared/distributed transactions; a failure here means the dtid transaction metadata could not be read (storage/backend error). The raw err.Error() text is written as the HTTP 500 body.

Source

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

	switch action {
	case "Discard", "Rollback":
		err = txe.RollbackPrepared(dtid, 0)
	case "Commit":
		err = txe.CommitPrepared(dtid)
	case "Conclude":
		err = txe.ConcludeTransaction(dtid)
	}
	var msg string
	if action != "" {
		if err != nil {
			msg = fmt.Sprintf("%s(%s): %v", r.FormValue("Action"), dtid, err)
		} else {
			msg = fmt.Sprintf("%s(%s): completed.", r.FormValue("Action"), dtid)
		}
	}
	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")

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Read the error body — it is the raw ReadTwopcInflight error — and fix the underlying storage/MySQL issue it names.
  2. Check vttablet logs for the full error with context around the /twopcz request.
  3. Verify the MySQL backend is healthy and the transaction metadata table (dtid store) exists and is readable; run a manual SELECT against it to confirm.
  4. Retry after restoring MySQL connectivity; if metadata is corrupt, follow the 2PC recovery runbook (ResolveTransactions/ConcludeTransaction) carefully to avoid data loss.
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm MySQL backend reachable before calling /twopcz
if err := mysqlPing(ctx, tabletDSN); err != nil {
    return fmt.Errorf("backend down, /twopcz will fail: %w", err)
}

Try / catch

resp, err := http.Get(tabletURL + "/twopcz")
if err != nil {
    return err
}
if resp.StatusCode == http.StatusInternalServerError {
    body, _ := io.ReadAll(resp.Body)
    return fmt.Errorf("ReadTwopcInflight failed: %s", body)
}

Prevention

When it happens

Trigger: An HTTP GET to the vttablet /twopcz endpoint (acl DEBUGGING required) where txe.ReadTwopcInflight() returns an error — e.g. the dtid table in the transaction metadata storage is unreadable/corrupt, the backing MySQL query fails, or the transaction store is not available.

Common situations: Investigating unresolved distributed transactions after a crash and the transaction metadata storage is damaged; probing /twopcz on a tablet whose MySQL backend is down; scripting /twopcz during a failover when the transaction store is temporarily inaccessible.

Related errors


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