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

  1. Read the wrapped cause: if tablets remain, drain/remove tablets first or pass Recursive=true
  2. Pass EvenIfServing=true only if you intend to delete a serving shard
  3. Verify all tablets are removed (GetTablets filtered by keyspace) before retrying
  4. 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

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


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