vitessio/vitess · error
cannot delete shard %v/%v: %w
Error message
cannot delete shard %v/%v: %w
What it means
DeleteKeyspace deletes each shard in the keyspace via deleteShard before removing the keyspace record itself. If any shard deletion fails, the operation aborts and the error is wrapped as 'cannot delete shard <keyspace>/<shard>: <cause>', leaving remaining shards and the keyspace untouched.
Source
Thrown at go/vt/vtctl/grpcvtctldserver/server.go:1188
return nil, err
}
if len(shards) > 0 {
if !req.Recursive {
err = vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "keyspace %v still has %d shards; use Recursive=true or remove them manually", req.Keyspace, len(shards))
return nil, err
}
log.Info(fmt.Sprintf("Deleting all %d shards (and their tablets) in keyspace %v", len(shards), req.Keyspace))
recursive := true
evenIfServing := true
force := req.Force
for _, shard := range shards {
log.Info(fmt.Sprintf("Recursively deleting shard %v/%v", req.Keyspace, shard))
err = deleteShard(ctx, s.ts, req.Keyspace, shard, recursive, evenIfServing, force)
if err != nil {
err = fmt.Errorf("cannot delete shard %v/%v: %w", req.Keyspace, shard, err)
return nil, err
}
}
}
cells, err := s.ts.GetKnownCells(ctx)
if err != nil {
return nil, err
}
for _, cell := range cells {
if err := s.ts.DeleteKeyspaceReplication(ctx, cell, req.Keyspace); err != nil && !topo.IsErrType(err, topo.NoNode) {
log.Warn(fmt.Sprintf("Cannot delete KeyspaceReplication in cell %v for %v: %v", cell, req.Keyspace, err))
}
if err := s.ts.DeleteSrvKeyspace(ctx, cell, req.Keyspace); err != nil && !topo.IsErrType(err, topo.NoNode) {
log.Warn(fmt.Sprintf("Cannot delete SrvKeyspace in cell %v for %v: %v", cell, req.Keyspace, err))
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Read the wrapped cause: if tablets remain, drain/remove tablets first or pass Recursive=true
- Pass EvenIfServing=true only if you intend to delete a serving shard
- Verify all tablets are removed (GetTablets filtered by keyspace) before retrying
- After shards are cleaned, retry DeleteKeyspace
Example fix
// before client.DeleteKeyspace(ctx, req) // after req.Recursive = true client.DeleteKeyspace(ctx, req)
Defensive patterns
Strategy: validation
Validate before calling
tablets, err := client.GetTablets(ctx, keyspace)
if len(tablets) > 0 {
return fmt.Errorf("keyspace still hosts %d tablets; drain first", len(tablets))
} Try / catch
_, err := client.DeleteKeyspace(ctx, req)
if err != nil && strings.Contains(err.Error(), "cannot delete shard") {
// read wrapped cause; remove tablets or pass Recursive=true
} Prevention
- Drain and remove all tablets before deleting a keyspace
- Set Recursive=true when you intend to delete non-empty shards
- Only use EvenIfServing=true deliberately
- Verify shard cleanup with GetShard after deletion
When it happens
Trigger: Deleting a keyspace whose shards cannot be removed: shard still has tablets (non-recursive delete), shard is serving (evenIfServing false), or the topo shard delete call fails.
Common situations: Keyspace still hosts tablets because reparenting/decommission was incomplete; recursive flag omitted; leftover serving checks; topo connectivity failures mid-delete.
Related errors
- old tablet has shard %v/%v. Cannot override with shard %v/%v
- %w: cannot delete keyspace in %s
- %w: cannot delete shards in %s
- cannot lookup primary tablet %v for shard %v/%v: %w
- unknown keyspace type %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/42c04941f02dc1f9.
Report an issue: GitHub.