{"record":{"id":"06cdaa2d3b3dacdb","repo":"vitessio/vitess","slug":"can-t-delete-tablet-v-v","errorCode":null,"errorMessage":"can't delete tablet %v: %v","messagePattern":"can't delete tablet (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/wrangler/shard.go","lineNumber":150,"sourceCode":"\t\t\t\treturn fmt.Errorf(\"shard %v/%v still has %v tablets in cell %v; use -recursive or remove them manually\", keyspace, shard, len(tabletMap), cell)\n\t\t\t}\n\n\t\t\twr.Logger().Infof(\"Deleting all tablets in shard %v/%v cell %v\", keyspace, shard, cell)\n\t\t\tfor tabletAlias, tabletInfo := range tabletMap {\n\t\t\t\t// We don't care about scrapping or updating the replication graph,\n\t\t\t\t// because we're about to delete the entire replication graph.\n\t\t\t\twr.Logger().Infof(\"Deleting tablet %v\", tabletAlias)\n\t\t\t\tif err := wr.TopoServer().DeleteTablet(ctx, tabletInfo.Alias); err != nil && !topo.IsErrType(err, topo.NoNode) {\n\t\t\t\t\t// We don't want to continue if a DeleteTablet fails for\n\t\t\t\t\t// any good reason (other than missing tablet, in which\n\t\t\t\t\t// case it's just a topology server inconsistency we can\n\t\t\t\t\t// ignore). If we continue and delete the replication\n\t\t\t\t\t// graph, the tablet record will be orphaned, since\n\t\t\t\t\t// we'll no longer know it belongs to this shard.\n\t\t\t\t\t//\n\t\t\t\t\t// If the problem is temporary, or resolved externally, re-running\n\t\t\t\t\t// DeleteShard will skip over tablets that were already deleted.\n\t\t\t\t\treturn fmt.Errorf(\"can't delete tablet %v: %v\", tabletAlias, err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Try to remove the replication graph and serving graph in each cell,\n\t// regardless of its existence.\n\tfor _, cell := range cells {\n\t\tif err := wr.ts.DeleteShardReplication(ctx, cell, keyspace, shard); err != nil && !topo.IsErrType(err, topo.NoNode) {\n\t\t\twr.Logger().Warningf(\"Cannot delete ShardReplication in cell %v for %v/%v: %v\", cell, keyspace, shard, err)\n\t\t}\n\t}\n\n\treturn wr.ts.DeleteShard(ctx, keyspace, shard)\n}\n\n// SourceShardDelete will delete a SourceShard inside a shard, by index.\n//","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/wrangler/shard.go#L132-L168","documentation":"In recursive DeleteShard, each remaining tablet is deleted via wr.DeleteTablet before removing the shard. If any tablet deletion fails (e.g. it is a primary with replicas, or topo update fails), the whole DeleteShard aborts so the replication graph is never removed while a tablet record would become orphaned.","triggerScenarios":"Recursive DeleteShard where wr.DeleteTablet(alias) returns an error for a tablet — typically deleting a primary tablet that still has serving replicas, or a transient topo write failure.","commonSituations":"Trying to tear down a shard whose primary still has followers; locked topo server (another vtctld operation holds the shard/keyspace lock); network blip mid-deletion.","solutions":["Read the inner error: if the tablet is a primary with replicas, first reparent or remove the replicas, then re-run DeleteShard -recursive.","Check for topo locks (another workflow like Reshard holding the keyspace lock) and wait/cancel it, then retry.","If the error was transient, simply re-run DeleteShard -recursive; it skips tablets already deleted."],"exampleFix":"// before\nvtctldclient DeleteShard -recursive commerce/0\n// error: can't delete tablet zone1-100: primary tablet has replicas\n// after\nvtctldclient PluralTabletsDelete --allow_primary zone1-100 zone1-101   # or remove replicas first\nvtctldclient DeleteShard -recursive commerce/0","handlingStrategy":"validation","validationCode":"// Before recursive delete, ensure primaries are demoted/removed\ntablets, _ := vtctldclientListTablets(keyspace, shard)\nfor _, t := range tablets {\n    if t.Type == \"PRIMARY\" {\n        // demote or delete replicas first\n        fmt.Printf(\"primary %s still present; handle replicas first\\n\", t.Alias)\n    }\n}","typeGuard":null,"tryCatchPattern":"// Go: re-run DeleteShard on transient tablet-delete failure\nerr := wr.DeleteShard(ctx, ks, shard, cells, true)\nif err != nil && strings.Contains(err.Error(), \"can't delete tablet\") {\n    // check topo locks, resolve, then retry (safe: skips already-deleted tablets)\n    err = wr.DeleteShard(ctx, ks, shard, cells, true)\n}","preventionTips":["Remove or reparent replicas before deleting a shard's primary","Check for concurrent topo-lock-holding workflows before shard teardown","Re-run DeleteShard -recursive after transient failures — it skips deleted tablets"],"tags":["topo","shard-deletion","tablets","wrangler"],"backgroundTag":"tablet-delete-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}