vitessio/vitess · critical

uncaught panic: %v, vtgate: %v

Error message

uncaught panic: %v, vtgate: %v

What it means

VTGate recovered from an unrecovered panic inside a request-handling goroutine. The panic value is re-thrown to the caller as an error with the vtgate listening URL appended so the client knows which gate instance handled (and crashed on) the request. A 'Panic' counter is also incremented with code INTERNAL.

Source

Thrown at go/vt/vtgate/vtgate.go:1027

		}
		// log only if sql query present and able to successfully redact the PII.
		logger.Infof("unsupported query: %q", piiSafeSQL)
	}
	return err
}

func formatError(err error) error {
	if err == nil {
		return nil
	}
	return err
}

// HandlePanic recovers from panics, and logs / increment counters
func (vtg *VTGate) HandlePanic(err *error) {
	if x := recover(); x != nil {
		log.Error(fmt.Sprintf("Uncaught panic:\n%v\n%s", x, tb.Stack(4)))
		*err = fmt.Errorf("uncaught panic: %v, vtgate: %v", x, servenv.ListeningURL.String())
		errorCounts.Add([]string{"Panic", "Unknown", "Unknown", vtrpcpb.Code_INTERNAL.String()}, 1)
	}
}

func newVTGate(executor *Executor, resolver *Resolver, vsm *vstreamManager, tc *TxConn, gw *TabletGateway) *VTGate {
	return &VTGate{
		executor:                executor,
		resolver:                resolver,
		vsm:                     vsm,
		txConn:                  tc,
		gw:                      gw,
		timings:                 timings,
		rowsReturned:            rowsReturned,
		rowsAffected:            rowsAffected,
		queryTextCharsProcessed: queryTextCharsProcessed,

		logExecute:       logutil.NewThrottledLogger("Execute", 5*time.Second),
		logPrepare:       logutil.NewThrottledLogger("Prepare", 5*time.Second),

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Read the full 'Uncaught panic:' stack trace in the vtgate log at the reported URL to identify the panicking function
  2. Check the panic value: nil-pointer on a nil session/plan usually indicates a client sending requests with unexpected fields
  3. Search Vitess issues for the panicking function; upgrade to a release containing the fix
  4. If reproducible, file a bug with the stack trace, query, and schema/vschema
  5. As mitigation, retry against a different vtgate instance since the panic is contained per-request

Example fix

// before: opaque INTERNAL error surfaced to client
// after: capture root cause from logs and avoid trigger
// log: Uncaught panic: runtime error: invalid memory address ... vtgate/exec.go:123
// action: upgrade Vitess to version fixing exec.go:123, or stop sending the offending query shape
Defensive patterns

Strategy: try-catch

Try / catch

res, err := vtgateConn.Execute(ctx, target, sql, bindVars)
if err != nil && strings.Contains(err.Error(), "uncaught panic") {
    // request killed vtgate internals; capture err (contains vtgate URL),
    // retry on another vtgate or report with the stack trace from server logs
    return nil, fmt.Errorf("vtgate panicked (%w); see server logs at reported URL", err)
}

Prevention

When it happens

Trigger: Any panic during query execution in vtgate (nil pointer in executor, malformed internal state, bug in a plugin/resolver) that is caught by the deferred HandlePanic(err) in the RPC handler wrappers.

Common situations: Hitting an untested code path in a query plan, a bug after a Vitess upgrade, corrupt session state, or concurrency bugs surfacing as nil dereferences during load.

Related errors


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