{"record":{"id":"d73bd5ad070447a2","repo":"vitessio/vitess","slug":"shard-v-v-still-has-v-tablets-in-cell-v-use","errorCode":null,"errorMessage":"shard %v/%v still has %v tablets in cell %v; use -recursive or remove them manually","messagePattern":"shard (.+?)/(.+?) still has (.+?) tablets in cell (.+?); use -recursive or remove them manually","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/wrangler/shard.go","lineNumber":132,"sourceCode":"\t\t// our purpose, it means a tablet was deleted but is\n\t\t// still referenced.\n\t\ttabletMap, err := wr.ts.GetTabletMap(ctx, aliases, nil)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"GetTabletMap() failed: %v\", err)\n\t\t}\n\n\t\t// Remove the tablets that don't belong to our\n\t\t// keyspace/shard from the map.\n\t\tfor a, ti := range tabletMap {\n\t\t\tif ti.Keyspace != keyspace || ti.Shard != shard {\n\t\t\t\tdelete(tabletMap, a)\n\t\t\t}\n\t\t}\n\n\t\t// Now see if we need to DeleteTablet, and if we can, do it.\n\t\tif len(tabletMap) > 0 {\n\t\t\tif !recursive {\n\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)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/wrangler/shard.go#L114-L150","documentation":"DeleteShard refuses to delete a shard while tablet records still exist in the topo, unless -recursive is passed. Non-recursive deletion only removes the shard record when no tablets remain, protecting you from orphaning live tablets.","triggerScenarios":"Running DeleteShard without the -recursive flag while the shard still contains tablet records in the given cell (after filtering out tablets not belonging to the keyspace/shard).","commonSituations":"Operators forget -recursive when tearing down an empty-ish shard that still has drained tablets registered; partial manual tablet deletion left some records behind.","solutions":["Run `vtctldclient DeleteShard -recursive <keyspace>/<shard>` to delete all remaining tablets along with the shard.","Or manually remove tablets first: `vtctldclient DeleteTablet <alias>` for each remaining tablet, then re-run DeleteShard without -recursive.","List the tablets with `vtctldclient GetTablets` (or ListTablets) to confirm which records remain before deleting."],"exampleFix":"// before\nvtctldclient DeleteShard commerce/0\n// error: still has 3 tablets in cell zone1\n// after\nvtctldclient DeleteShard -recursive commerce/0","handlingStrategy":"validation","validationCode":"// Before DeleteShard, check the shard is empty\nshardInfo, _ := vtctldclientGetShard(keyspace, shard)\ntablets, _ := vtctldclientListTablets(keyspace, shard)\nif len(tablets) > 0 {\n    // plan: delete each tablet first, or use -recursive\n    fmt.Printf(\"shard %s/%s still has %d tablets\\n\", keyspace, shard, len(tablets))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always list tablets (`vtctldclient GetTablets`) before deleting a shard","Use -recursive intentionally, never by default in scripts","Drain and remove tablets as part of the decommission runbook before shard deletion"],"tags":["topo","shard-deletion","tablets","safety-guard"],"backgroundTag":"shard-not-empty","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}