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

  1. Migrate to the VExplain API, setting ClusterId, Keyspace, and Sql
  2. If VTExplain must still be used, populate req.Cluster with the registered cluster ID
  3. 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

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


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