vitessio/vitess · error · errors.BadRequest
must specify at least one keyspace_shard to delete (got %+v)
Error message
must specify at least one keyspace_shard to delete (got %+v)
What it means
DeleteShards requires at least one shard to operate on; if the parsed shard list is empty, the handler returns a 400 BadRequest telling the caller to specify at least one keyspace_shard. This guards the vtctld DeleteShards RPC, which would otherwise fail downstream, by rejecting the request early with a clear message.
Source
Thrown at go/vt/vtadmin/http/shards.go:92
shards := make([]*vtctldatapb.Shard, len(shardList))
for i, kss := range shardList {
ks, shard, err := topoproto.ParseKeyspaceShard(kss)
if err != nil {
return NewJSONResponse(nil, &errors.BadRequest{
Err: fmt.Errorf("%w: parsing %s at position %d", err, kss, i),
})
}
shards[i] = &vtctldatapb.Shard{
Keyspace: ks,
Name: shard,
Shard: &topodatapb.Shard{},
}
}
if len(shards) == 0 {
return NewJSONResponse(nil, &errors.BadRequest{
Err: fmt.Errorf("must specify at least one keyspace_shard to delete (got %+v)", shardList),
})
}
resp, err := api.server.DeleteShards(ctx, &vtadminpb.DeleteShardsRequest{
ClusterId: vars["cluster_id"],
Options: &vtctldatapb.DeleteShardsRequest{
Shards: shards,
Recursive: recursive,
EvenIfServing: evenIfServing,
},
})
return NewJSONResponse(resp, err)
}
// EmergencyFailoverShard implements the http wrapper for
// POST /shard/{cluster_id}/{keyspace}/{shard}/emergency_failover.
//
// Query params: noneView on GitHub (pinned to 01a25a7d17)
Solutions
- Include at least one valid keyspace_shard query parameter, e.g. ?keyspace_shard=commerce/0.
- Client-side: check the selected shard list is non-empty before issuing the request.
- Filter out empty strings before sending so blank entries don't produce a request with no real targets.
Example fix
// before
const qs = shards.map(s => `keyspace_shard=${s}`).join('&')
// after
if (shards.length === 0) throw new Error('select at least one shard')
const qs = shards.map(s => `keyspace_shard=${encodeURIComponent(s)}`).join('&') Defensive patterns
Strategy: validation
Validate before calling
shards := nonEmpty(keyspaceShards)
if len(shards) == 0 {
return errors.New("must provide at least one keyspace_shard")
} Try / catch
resp, err := http.Post(u, "application/json", body)
if err == nil && resp.StatusCode == 400 {
var e vtadminErr
_ = json.NewDecoder(resp.Body).Decode(&e)
return fmt.Errorf("request invalid: %v", e)
} Prevention
- Require shard selection in the UI/API client before enabling the delete action.
- Filter empty strings before serializing query parameters.
- Add a client-side assertion that len(shards) > 0 before sending.
When it happens
Trigger: Calling the delete-shards endpoint without any `keyspace_shard` query parameters, or with only empty values such that the parsed shard list is zero-length.
Common situations: Client omits the query parameter entirely; UI sends an empty selection; list built from a split of an empty string producing an empty/blank list.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- %w: parsing %s at position %d
- unsupported config format
- %w: %s
- %w: clusterID is required
- %w: keyspace name is required
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/95a3501ddea30066.
Report an issue: GitHub.