{"record":{"id":"cb6802610e6508fa","repo":"vitessio/vitess","slug":"old-tablet-has-shard-v-v-cannot-override-with-s","errorCode":null,"errorMessage":"old tablet has shard %v/%v. Cannot override with shard %v/%v. Delete and re-add tablet if you want to change the tablet's keyspace/shard","messagePattern":"old tablet has shard (.+?)/(.+?)\\. Cannot override with shard (.+?)/(.+?)\\. Delete and re-add tablet if you want to change the tablet's keyspace/shard","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/topo/tablet.go","lineNumber":643,"sourceCode":"\n\tif tablet.Type == topodatapb.TabletType_PRIMARY {\n\t\t// we update primary_term_start_time even if the primary hasn't changed\n\t\t// because that means a new primary term with the same primary\n\t\ttablet.PrimaryTermStartTime = protoutil.TimeToProto(time.Now())\n\t}\n\n\terr = ts.CreateTablet(ctx, tablet)\n\tif IsErrType(err, NodeExists) && allowUpdate {\n\t\t// Try to update then\n\t\toldTablet, err := ts.GetTablet(ctx, tablet.Alias)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed reading existing tablet %v: %v\", topoproto.TabletAliasString(tablet.Alias), err)\n\t\t}\n\n\t\t// Check we have the same keyspace / shard, and if not,\n\t\t// require the allowDifferentShard flag.\n\t\tif oldTablet.Keyspace != tablet.Keyspace || oldTablet.Shard != tablet.Shard {\n\t\t\treturn fmt.Errorf(\"old tablet has shard %v/%v. Cannot override with shard %v/%v. Delete and re-add tablet if you want to change the tablet's keyspace/shard\", oldTablet.Keyspace, oldTablet.Shard, tablet.Keyspace, tablet.Shard)\n\t\t}\n\t\toldTablet.Tablet = tablet.CloneVT()\n\t\tif err := ts.UpdateTablet(ctx, oldTablet); err != nil {\n\t\t\treturn fmt.Errorf(\"failed updating tablet %v: %v\", topoproto.TabletAliasString(tablet.Alias), err)\n\t\t}\n\t\treturn nil\n\t}\n\treturn err\n}\n\n// ParseServingTabletType parses the tablet type into the enum, and makes sure\n// that the enum is of serving type (PRIMARY, REPLICA, RDONLY/BATCH).\n//\n// Note: This function more closely belongs in topoproto, but that would create\n// a circular import between packages topo and topoproto.\nfunc ParseServingTabletType(param string) (topodatapb.TabletType, error) {\n\tservedType, err := topoproto.ParseTabletType(param)\n\tif err != nil {","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/topo/tablet.go#L625-L661","documentation":"InitTablet with allowUpdate=true found an existing tablet record whose keyspace or shard differs from the one being registered. Vitess refuses to silently re-home a tablet into another shard because that would corrupt the serving topology. The fix requires explicitly deleting and re-adding the tablet, or passing the allowDifferentShard flag where available.","triggerScenarios":"Calling InitTablet for an alias already registered under a different keyspace/shard while allowUpdate is true and the allowDifferentShard precondition (same keyspace/shard) fails. Common via vttablet startup with a changed -keyspace/-shard flag, or test helpers addTablet/NewFakeTablet reusing UIDs.","commonSituations":"Operator edits vttablet's -shard or -keyspace flag but the old tablet record still exists in topo; reusing tablet UIDs across environments; copied Vitess configs pointing a tablet at a new shard without cleanup.","solutions":["Delete the old tablet record: vtctldclient DeleteTablet <alias> (after ensuring it's not serving), then re-run InitTablet","Correct the -keyspace/-shard flags on vttablet to match the existing registration","If re-homing is intentional, use the flow that sets allowDifferentShard explicitly rather than plain InitTablet"],"exampleFix":"// before\nvttablet -tablet_alias zone1-100 -keyspace commerce -shard 0\n// after (record exists in commerce/1)\nvtctldclient DeleteTablet zone1-100\nvttablet -tablet_alias zone1-100 -keyspace commerce -shard 1","handlingStrategy":"validation","validationCode":"old, err := ts.GetTablet(ctx, alias)\nif err == nil && (old.Keyspace != keyspace || old.Shard != shard) {\n    return fmt.Errorf(\"alias %v registered in %v/%v; delete it first\", alias, old.Keyspace, old.Shard)\n}","typeGuard":null,"tryCatchPattern":"if err := ts.InitTablet(ctx, tablet, false, true, false); err != nil {\n    if strings.Contains(err.Error(), \"Cannot override with shard\") {\n        // handle shard mismatch: delete + re-add, or fix flags\n    }\n    return err\n}","preventionTips":["Keep -keyspace/-shard flags in sync with existing registrations","Run vtctldclient GetTablets before re-provisioning an alias","Automate teardown of tablet records in test environments","Never reuse tablet UIDs across shards without cleanup"],"tags":["topo","tablet-registration","keyspace","shard"],"backgroundTag":"tablet-shard-mismatch","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}