vitessio/vitess · error · ErrInvalidRequest

%w: clusterID is required

Error message

%w: clusterID is required

What it means

VExplain validates the request before executing; an empty cluster_id fails with ErrInvalidRequest wrapped by this message. It is a pure client-input validation error — no cluster lookup or query occurs.

Source

Thrown at go/vt/vtadmin/api.go:2611

	res, err := c.Vtctld.ValidateVersionShard(ctx, &vtctldatapb.ValidateVersionShardRequest{
		Keyspace: req.Keyspace,
		Shard:    req.Shard,
	})
	if err != nil {
		return nil, err
	}

	return res, nil
}

// VExplain is part of the vtadminpb.VTAdminServer interface.
func (api *API) VExplain(ctx context.Context, req *vtadminpb.VExplainRequest) (*vtadminpb.VExplainResponse, error) {
	span, ctx := trace.NewSpan(ctx, "API.VExplain")
	defer span.Finish()

	if req.ClusterId == "" {
		return nil, fmt.Errorf("%w: clusterID 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.ClusterId)
	if err != nil {
		return nil, err
	}

	if !api.authz.IsAuthorized(ctx, c.ID, rbac.VExplainResource, rbac.GetAction) {
		return nil, nil
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Set ClusterId to a valid registered cluster ID in the VExplainRequest before sending
  2. Check client code that builds the request for a dropped/renamed field
  3. Validate required fields client-side before issuing the RPC

Example fix

// before
req := &vtadminpb.VExplainRequest{Keyspace: "ks", Sql: q}
// after
req := &vtadminpb.VExplainRequest{ClusterId: "prod-main", Keyspace: "ks", Sql: q}
Defensive patterns

Strategy: validation

Validate before calling

func validateVExplainRequest(clusterID, keyspace, sql string) error {
    if clusterID == "" {
        return errors.New("clusterID is required")
    }
    if keyspace == "" {
        return errors.New("keyspace is required")
    }
    if sql == "" {
        return errors.New("sql is required")
    }
    return nil
}

Type guard

func vExplainRequestValid(req *vtadminpb.VExplainRequest) bool {
    return req != nil && req.ClusterId != "" && req.Keyspace != "" && req.Sql != ""
}

Try / catch

if err := validateVExplainRequest(req.ClusterId, req.Keyspace, req.Sql); err != nil {
    return err
}
resp, err := client.VExplain(ctx, req)

Prevention

When it happens

Trigger: Calling API.VExplain with a VExplainRequest whose ClusterId field is the empty string.

Common situations: Client SDK constructed the request without setting ClusterId; UI passed only keyspace/sql; migrating from VTExplain (which uses req.Cluster) to VExplain and forgetting to rename/populate the field.

Related errors


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