vitessio/vitess · error
shard %v/%v is still serving, cannot delete it, use even_if_
Error message
shard %v/%v is still serving, cannot delete it, use even_if_serving flag if needed
What it means
DeleteShard refuses to delete a shard whose Serving map still lists it in at least one cell, unless the caller passes evenIfServing. This is a safety guard: deleting a shard that vtgates are still routing traffic to would cause immediate query failures.
Source
Thrown at go/vt/wrangler/shard.go:75
// Read the Shard object. If it's not there, try to clean up
// the topology anyway.
shardInfo, err := wr.ts.GetShard(ctx, keyspace, shard)
if err != nil {
if topo.IsErrType(err, topo.NoNode) {
wr.Logger().Infof("Shard %v/%v doesn't seem to exist, cleaning up any potential leftover", keyspace, shard)
return wr.ts.DeleteShard(ctx, keyspace, shard)
}
return err
}
servingCells, err := wr.ts.GetShardServingCells(ctx, shardInfo)
if err != nil {
return err
}
// Check the Serving map for the shard, we don't want to
// remove a serving shard if not absolutely sure.
if !evenIfServing && len(servingCells) > 0 {
return fmt.Errorf("shard %v/%v is still serving, cannot delete it, use even_if_serving flag if needed", keyspace, shard)
}
cells, err := wr.ts.GetCellInfoNames(ctx)
if err != nil {
return err
}
// Go through all the cells.
for _, cell := range cells {
var aliases []*topodatapb.TabletAlias
// Get the ShardReplication object for that cell. Try
// to find all tablets that may belong to our shard.
sri, err := wr.ts.GetShardReplication(ctx, cell, keyspace, shard)
switch {
case topo.IsErrType(err, topo.NoNode):
// No ShardReplication object. It means the
// topo is inconsistent. Let's read all theView on GitHub (pinned to 01a25a7d17)
Solutions
- Confirm no vtgate traffic uses the shard, then rerun with the even_if_serving flag.
- If traffic already moved, rebuild/refresh the serving graph so the shard is no longer marked serving.
- Double-check keyspace/shard names - a typo may target a live shard.
Example fix
// before vtctldclient DeleteShard customer/0 // after (verified no traffic) vtctldclient DeleteShard --even_if_serving customer/0
Defensive patterns
Strategy: validation
Validate before calling
shardInfo, err := ts.GetShard(ctx, keyspace, shard)
if err == nil {
for cell, serving := range shardInfo.ServingCells() /* or check serving map */ {
if serving && !evenIfServing {
return fmt.Errorf("shard %s/%s still serving in %s", keyspace, shard, cell)
}
}
} Type guard
func isServing(servingCells []string) bool { return len(servingCells) > 0 } Try / catch
err := wr.DeleteShard(ctx, keyspace, shard, evenIfServing, recursive)
if err != nil && strings.Contains(err.Error(), "is still serving") {
// confirm traffic moved, rerun with evenIfServing=true
} Prevention
- Verify the vtgate serving graph shows the shard as non-serving before deletion.
- Use even_if_serving only after explicit confirmation of no traffic.
- Double-check keyspace/shard names before destructive ops.
When it happens
Trigger: vtctldclient DeleteShard is run on a shard still marked serving in one or more cells without the --even_if_serving flag.
Common situations: Cleaning up after a reshard where the new shards weren't fully switched over; accidentally targeting a still-live shard; stale serving entries after traffic moved but the topo wasn't refreshed.
Related errors
- not allowed: read-only security-policy enforced
- shard not found
- no primary tablet found
- failed to get shard %s/%s: %v
- shard %s/%s has no primary
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/b6b963dd10f174b6.
Report an issue: GitHub.