vitessio/vitess · error
can't get primary tablet record %v: %v
Error message
can't get primary tablet record %v: %v
What it means
After finding the shard's PrimaryAlias, getPrimaryPosition fetches the full tablet record via ts.GetTablet. If that record cannot be read from the topo, this error wraps the alias and the underlying cause. It usually means the shard record points at a primary that no longer exists in the topo.
Source
Thrown at go/vt/mysqlctl/builtinbackupengine.go:1837
// ShouldStartMySQLAfterRestore signifies if this backup engine needs to restart MySQL once the restore is completed.
func (be *BuiltinBackupEngine) ShouldStartMySQLAfterRestore() bool {
return true
}
func (be *BuiltinBackupEngine) Name() string { return builtinBackupEngineName }
func getPrimaryPosition(ctx context.Context, tmc tmclient.TabletManagerClient, ts *topo.Server, keyspace, shard string) (replication.Position, error) {
si, err := ts.GetShard(ctx, keyspace, shard)
if err != nil {
return replication.Position{}, vterrors.Wrap(err, "can't read shard")
}
if topoproto.TabletAliasIsZero(si.PrimaryAlias) {
return replication.Position{}, fmt.Errorf("shard %v/%v has no primary", keyspace, shard)
}
ti, err := ts.GetTablet(ctx, si.PrimaryAlias)
if err != nil {
return replication.Position{}, fmt.Errorf("can't get primary tablet record %v: %v", topoproto.TabletAliasString(si.PrimaryAlias), err)
}
posStr, err := tmc.PrimaryPosition(ctx, ti.Tablet)
if err != nil {
return replication.Position{}, fmt.Errorf("can't get primary replication position: %v", err)
}
pos, err := replication.DecodePosition(posStr)
if err != nil {
return replication.Position{}, fmt.Errorf("can't decode primary replication position %q: %v", posStr, err)
}
return pos, nil
}
func init() {
BackupRestoreEngineMap[builtinBackupEngineName] = &BuiltinBackupEngine{}
}
// closeWithRetry does just what it says. Retrying a close operation is important as
// an error is most likely transient/ephemeral and leaving around open file descriptorsView on GitHub (pinned to 01a25a7d17)
Solutions
- Read the wrapped cause to see if it is a node-not-found from topo.
- Inspect the shard record's PrimaryAlias and compare with actual tablets (vtctldclient GetTablets).
- Run EmergencyReparentShard or re-initialize the shard so PrimaryAlias points to a live tablet.
- Prune stale tablet records from the topo and re-run the operation.
Defensive patterns
Strategy: validation
Validate before calling
si, _ := ts.GetShard(ctx, keyspace, shard)
if _, err := ts.GetTablet(ctx, si.PrimaryAlias); err != nil {
// stale PrimaryAlias: reparent or clean topo before proceeding
} Try / catch
if _, err := getPrimaryPosition(ctx, tmc, ts, ks, shard); err != nil {
if strings.Contains(err.Error(), "can't get primary tablet record") {
// refresh shard record / run ERS to fix stale alias
}
} Prevention
- Delete tablet records and update shard aliases atomically during decommission.
- Monitor for shards whose PrimaryAlias has no matching tablet record.
- Run topo consistency checks regularly.
When it happens
Trigger: ts.GetTablet(ctx, si.PrimaryAlias) fails because the primary tablet record was deleted from topo (e.g. tablet fully removed after failover) while the shard record still references the stale alias.
Common situations: Stale PrimaryAlias after a primary was deleted or rebuilt; topo backend inconsistency (etcd/zookeeper) after partial failover; typo'd cell in tablet record cleanup.
Related errors
- shard %v/%v has no primary
- cannot get (or create) shard %v/%v: %v
- shard %v/%v has a different KeyRange: %v != %v
- old tablet has shard %v/%v. Cannot override with shard %v/%v
- invalid shard path: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/9d6aa41ad027fd3d.
Report an issue: GitHub.