vitessio/vitess · warning · ErrInvalidRequest
%w: cluster ID is required
Error message
%w: cluster ID is required
What it means
The deprecated VTExplain RPC validates req.Cluster and returns this ErrInvalidRequest-wrapped error when it is empty. This endpoint is deprecated in favor of VExplain, so the durable fix is to migrate off it.
Source
Thrown at go/vt/vtadmin/api.go:2669
canonicalQuery := sqlparser.String(vexplainStmt)
response, err := c.DB.VExplain(ctx, canonicalQuery, vexplainStmt)
if err != nil {
return nil, err
}
return response, nil
}
// VTExplain is part of the vtadminpb.VTAdminServer interface.
func (api *API) VTExplain(ctx context.Context, req *vtadminpb.VTExplainRequest) (*vtadminpb.VTExplainResponse, error) {
// TODO (andrew): https://github.com/vitessio/vitess/issues/12161.
log.Warn("VTAdminServer.VTExplain is deprecated; please use a vexplain query instead. For more details, see https://vitess.io/docs/user-guides/sql/vexplain/.")
span, ctx := trace.NewSpan(ctx, "API.VTExplain")
defer span.Finish()
if req.Cluster == "" {
return nil, fmt.Errorf("%w: cluster ID is required", errors.ErrInvalidRequest)
}
if req.Keyspace == "" {
return nil, fmt.Errorf("%w: keyspace name is required", errors.ErrInvalidRequest)
}
if req.Sql == "" {
return nil, fmt.Errorf("%w: SQL query is required", errors.ErrInvalidRequest)
}
c, err := api.getClusterForRequest(req.Cluster)
if err != nil {
return nil, err
}
span.Annotate("keyspace", req.Keyspace)
cluster.AnnotateSpan(c, span)
View on GitHub (pinned to 01a25a7d17)
Solutions
- Migrate to the VExplain API, setting ClusterId, Keyspace, and Sql
- If VTExplain must still be used, populate req.Cluster with the registered cluster ID
- Update old clients/scripts still calling VTExplain
Example fix
// before
req := &vtadminpb.VTExplainRequest{Keyspace: "ks", Sql: q}
// after
req := &vtadminpb.VExplainRequest{ClusterId: "prod-main", Keyspace: "ks", Sql: q} Defensive patterns
Strategy: validation
Validate before calling
func validateVTExplainRequest(cluster, keyspace, sql string) error {
if cluster == "" {
return errors.New("cluster ID is required")
}
if keyspace == "" {
return errors.New("keyspace name is required")
}
if sql == "" {
return errors.New("SQL query is required")
}
return nil
} Type guard
func vtExplainRequestValid(req *vtadminpb.VTExplainRequest) bool {
return req != nil && req.Cluster != "" && req.Keyspace != "" && req.Sql != ""
} Try / catch
if !vtExplainRequestValid(req) {
return errors.New("VTExplain requires cluster, keyspace and sql; prefer VExplain instead")
}
resp, err := client.VTExplain(ctx, req) Prevention
- Migrate to VExplain (ClusterId-based) to avoid the deprecated endpoint
- Update legacy clients to populate req.Cluster if VTExplain must still be used
- Track deprecation warnings and fix call sites before the endpoint is removed
When it happens
Trigger: Calling API.VTExplain with req.Cluster == "" (or using an old client that never populated the Cluster field).
Common situations: Old scripts/SDKs predating the VExplain rename; refactoring requests from VTExplain to VExplain left the deprecated call path with unset fields; deprecation warnings ignored until the field name mismatch surfaced.
Related errors
- %w: clusterID is required
- %w: %s
- %w: keyspace name is required
- %w: SQL query is required
- %w: request cannot be nil
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/09db353b47c58213.
Report an issue: GitHub.