vitessio/vitess · error

cannot delete tablet %v: %w

Error message

cannot delete tablet %v: %w

What it means

deleteShardCell wraps a per-tablet DeleteTablet failure. If a tablet cannot be deleted (other than a transient-case handled internally), shard deletion aborts for that cell so tablet records are never orphaned from the shard.

Source

Thrown at go/vt/vtctl/grpcvtctldserver/topo.go:200

		}

		log.Info(fmt.Sprintf("Deleting all %d tablets in shard %v/%v cell %v", len(tabletMap), keyspace, shard, cell))
		for alias, tablet := range tabletMap {
			// We don't care about updating the ShardReplication object, because
			// later we're going to delete the entire object.
			log.Info(fmt.Sprintf("Deleting tablet %v", alias))
			if err := ts.DeleteTablet(ctx, tablet.Alias); err != nil && !topo.IsErrType(err, topo.NoNode) {
				// We don't want to continue if a DeleteTablet fails for any
				// reason other than a missing tablet (in which case it's just
				// topo server inconsistency, which we can ignore). If we were
				// to continue and delete the replication graph, the tablet
				// record would become orphaned, since we'd no longer know that
				// it belongs to this shard.
				//
				// If the problem is temporary, or resolved externally,
				// re-running DeleteShard will skip over tablets that were
				// already deleted.
				return fmt.Errorf("cannot delete tablet %v: %w", alias, err)
			}
		}
	}

	return nil
}

func deleteTablet(ctx context.Context, ts *topo.Server, alias *topodatapb.TabletAlias, allowPrimary bool) (err error) {
	span, ctx := trace.NewSpan(ctx, "VtctldServer.deleteTablet")
	defer span.Finish()

	span.Annotate("tablet_alias", topoproto.TabletAliasString(alias))
	span.Annotate("allow_primary", allowPrimary)

	tablet, err := ts.GetTablet(ctx, alias)
	if err != nil {
		return err
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Stop/scrap the vttablet process(es) for the named alias, then re-run DeleteShard (it skips already-deleted tablets)
  2. Use vtctldclient DeleteTablet --allow_primary/--recursive on the offending tablet first
  3. Check replication graph references: vtctldclient GetShardReplication <cell> <keyspace/shard> and repair
  4. Retry once the temporary topo error resolves

Example fix

// before
vtctldclient DeleteShard --recursive ks/shard  # cannot delete tablet cell-0000010100
// after
vtctldclient DeleteTablet --allow_primary cell-0000010100
vtctldclient DeleteShard --recursive ks/shard
Defensive patterns

Strategy: validation

Validate before calling

// Ensure tablets are scrap-able before shard deletion
for _, t := range tablets {
	if t.Type == topodatapb.TabletType_PRIMARY {
		return fmt.Errorf("tablet %s still primary; demote/delete first", topoproto.TabletAliasString(t.Alias))
	}
}

Try / catch

if err := vtctldClient.DeleteShard(ctx, ks, shard); err != nil {
	var alias string
	if n, _ := fmt.Sscanf(err.Error(), "cannot delete tablet %s", &alias); n == 1 {
		_ = vtctldClient.DeleteTablet(ctx, alias) // clean the blocker, retry
	}
}

Prevention

When it happens

Trigger: During DeleteShard, ts.DeleteTablet(ctx, alias) fails for a tablet still referenced by the shard/replication graph, or a topo error occurs while deleting the tablet record.

Common situations: Tablet still running and holding topo locks; replication graph references the tablet; stale tablet record whose underlying vttablet process still exists; topo write error mid-deletion.

Related errors


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