vitessio/vitess · error
cannot lookup primary tablet %v for shard %v/%v: %w
Error message
cannot lookup primary tablet %v for shard %v/%v: %w
What it means
GetShardPrimaryForTablet first confirms the shard has a primary alias, then fetches the full tablet record for that alias. If the GetTablet lookup fails, the error is wrapped as 'cannot lookup primary tablet %v for shard %v/%v' with the alias, keyspace/shard, and underlying topo error, preserving the cause via %w.
Source
Thrown at go/vt/topotools/tablet.go:204
//
// It returns an error if:
// - The shard does not exist in the topo.
// - The shard has no primary in the topo.
// - The shard primary does not think it is PRIMARY.
// - The shard primary tablet record does not match the keyspace and shard of the replica.
func GetShardPrimaryForTablet(ctx context.Context, ts *topo.Server, tablet *topodatapb.Tablet) (*topo.TabletInfo, error) {
shard, err := ts.GetShard(ctx, tablet.Keyspace, tablet.Shard)
if err != nil {
return nil, err
}
if !shard.HasPrimary() {
return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "no primary tablet for shard %v/%v", tablet.Keyspace, tablet.Shard)
}
shardPrimary, err := ts.GetTablet(ctx, shard.PrimaryAlias)
if err != nil {
return nil, fmt.Errorf("cannot lookup primary tablet %v for shard %v/%v: %w", topoproto.TabletAliasString(shard.PrimaryAlias), tablet.Keyspace, tablet.Shard, err)
}
if shardPrimary.Type != topodatapb.TabletType_PRIMARY {
return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "TopologyServer has inconsistent state for shard primary %v", topoproto.TabletAliasString(shard.PrimaryAlias))
}
if shardPrimary.Keyspace != tablet.Keyspace || shardPrimary.Shard != tablet.Shard {
return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "primary %v and potential replica %v not in same keyspace shard (%v/%v)", topoproto.TabletAliasString(shard.PrimaryAlias), topoproto.TabletAliasString(tablet.Alias), tablet.Keyspace, tablet.Shard)
}
return shardPrimary, nil
}
// IsPrimaryTablet is a helper function to determine whether the current tablet
// is a primary before we allow its tablet record to be deleted. The canonical
// way to determine the only true primary in a shard is to list all the tablets
// and find the one with the highest PrimaryTermStartTime among the ones that
// claim to be primary.View on GitHub (pinned to 01a25a7d17)
Solutions
- Fix the underlying topo lookup error (check the wrapped cause): ensure the topo server is reachable and the tablet record for the primary alias exists.
- If the primary record is truly gone, run a reparenting flow (e.g. vtctldclient PlannedReparentShard or EmergencyReparentShard) to elect a valid primary and update the shard record.
- Verify shard consistency with vtctldclient GetShard and reconcile stale PrimaryAlias values.
Example fix
// before: no guard against missing primary record
primary, err := topotools.GetShardPrimaryForTablet(ctx, ts, tablet)
// after: check shard state first
shard, _ := ts.GetShard(ctx, tablet.Keyspace, tablet.Shard)
if shard != nil && shard.PrimaryAlias != nil {
if _, err := ts.GetTablet(ctx, shard.PrimaryAlias); err != nil {
return fmt.Errorf("primary alias %v missing from topo; run a reparent", topoproto.TabletAliasString(shard.PrimaryAlias))
}
}
primary, err := topotools.GetShardPrimaryForTablet(ctx, ts, tablet) Defensive patterns
Strategy: validation
Validate before calling
shard, err := ts.GetShard(ctx, keyspace, shard)
if err != nil {
return err
}
if shard.PrimaryAlias != nil {
if _, err := ts.GetTablet(ctx, shard.PrimaryAlias); err != nil {
return fmt.Errorf("primary %v record missing; reparent needed",
topoproto.TabletAliasString(shard.PrimaryAlias))
}
} Type guard
func primaryRecordExists(ctx context.Context, ts topo.Server, shard *topo.ShardInfo) bool {
if !shard.HasPrimary() {
return false
}
_, err := ts.GetTablet(ctx, shard.PrimaryAlias)
return err == nil
} Try / catch
primary, err := topotools.GetShardPrimaryForTablet(ctx, ts, tablet)
if err != nil {
if strings.Contains(err.Error(), "cannot lookup primary tablet") {
return fmt.Errorf("shard record stale/primary record missing; run reparent: %w", err)
}
return err
} Prevention
- Never delete a tablet record that is still listed as a shard primary — reparent first
- Monitor shard records for primary aliases whose tablet records cannot be fetched
- After decommissioning a primary, always run a reparent flow to update the shard record
When it happens
Trigger: Calling GetShardPrimaryForTablet (via SetReplicationSource or reparenting flows) when the shard record lists a PrimaryAlias but the tablet record for that alias cannot be read from the topo — deleted record, topo server down, or alias corruption.
Common situations: The primary tablet record was manually deleted from the topo while the shard record still points to it; a topo outage during a reparent; stale shard record after the primary was decommissioned without a proper reparent.
Related errors
- shard %v/%v has no primary
- invalid key:value pair
- Last_SQL_Error: ${LastSQL_Error}, Last_IO_Error: ${LastIO_Er
- GetPreviousGTIDs: previous GTIDs not found
- ErrNoSemiSync
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/be6f36fd28198b04.
Report an issue: GitHub.