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

  1. 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.
  2. 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.
  3. 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

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


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/be6f36fd28198b04. Report an issue: GitHub.