vitessio/vitess · error

no primary in shard %v/%v

Error message

no primary in shard %v/%v

What it means

After loading the shard record, ValidateShard requires the shard to have a serving primary tablet. If shard.HasPrimary() is false, it fails with "no primary in shard %v/%v" because the primary's version/schema cannot be used as the reference.

Source

Thrown at go/vt/vtctl/grpcvtctldserver/server.go:5413

	return resp, err
}

// ValidateVersionShard validates all versions are the same in all
// tablets in a shard
func (s *VtctldServer) ValidateVersionShard(ctx context.Context, req *vtctldatapb.ValidateVersionShardRequest) (resp *vtctldatapb.ValidateVersionShardResponse, err error) {
	span, ctx := trace.NewSpan(ctx, "VtctldServer.ValidateVersionShard")
	defer span.Finish()

	defer panicHandler(&err)

	shard, err := s.ts.GetShard(ctx, req.Keyspace, req.Shard)
	if err != nil {
		err = fmt.Errorf("GetShard(%s) failed: %v", req.Shard, err)
		return nil, err
	}

	if !shard.HasPrimary() {
		err = fmt.Errorf("no primary in shard %v/%v", req.Keyspace, req.Shard)
		return nil, err
	}

	log.Info(fmt.Sprintf("Gathering version for primary %v", topoproto.TabletAliasString(shard.PrimaryAlias)))
	primaryVersion, err := s.GetVersion(ctx, &vtctldatapb.GetVersionRequest{
		TabletAlias: shard.PrimaryAlias,
	})
	if err != nil {
		err = fmt.Errorf("GetVersion(%s) failed: %v", topoproto.TabletAliasString(shard.PrimaryAlias), err)
		return nil, err
	}

	aliases, err := s.ts.FindAllTabletAliasesInShard(ctx, req.Keyspace, req.Shard)
	if err != nil {
		err = fmt.Errorf("FindAllTabletAliasesInShard(%s, %s) failed: %v", req.Keyspace, req.Shard, err)
		return nil, err
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Initialize the primary: vtctldclient InitShardPrimary <keyspace>/<shard> <tablet-alias>.
  2. Complete or re-run PlannedReparentShard / EmergencyReparentShard if a failover was interrupted.
  3. Confirm with vtctldclient GetShard <keyspace>/<shard> that a primary alias is present before validating.

Example fix

// before
vtctldclient ValidateShard commerce 0   // fails: no primary
// after
vtctldclient InitShardPrimary commerce/0 zone1-0000000100
vtctldclient ValidateShard commerce 0
Defensive patterns

Strategy: validation

Validate before calling

shardInfo, err := ts.GetShard(ctx, ks, shard); if err == nil && !shardInfo.HasPrimary() { return fmt.Errorf("shard %s/%s has no primary; run InitShardPrimary first", ks, shard) }

Try / catch

if err != nil && strings.Contains(err.Error(), "no primary in shard") { /* initiate reparent or InitShardPrimary before retrying */ }

Prevention

When it happens

Trigger: Calling ValidateShard (or GetVersion flow) on a shard whose Shard record has no PrimaryAlias set — typically during a primary failover, after ERS/PRS was interrupted, or before InitShardPrimary.

Common situations: Shard freshly created but primary not initialized; failover in progress; primary tablet was deleted without electing a new one.

Related errors


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