vitessio/vitess · error

shard %v/%v has no primary

Error message

shard %v/%v has no primary

What it means

WaitForFilteredReplication reads replication lag from the shard's primary tablet, addressed via the shard record's PrimaryAlias. If the shard record has no primary (PrimaryAlias unset), lag cannot be measured and the call fails.

Source

Thrown at go/vt/wrangler/split.go:89

		}

		si.SourceShards = sourceShards
		return nil
	})
	return err
}

// WaitForFilteredReplication will wait until the Filtered Replication process has finished.
func (wr *Wrangler) WaitForFilteredReplication(ctx context.Context, keyspace, shard string, maxDelay time.Duration) error {
	shardInfo, err := wr.TopoServer().GetShard(ctx, keyspace, shard)
	if err != nil {
		return err
	}
	if len(shardInfo.SourceShards) == 0 {
		return fmt.Errorf("shard %v/%v has no source shard", keyspace, shard)
	}
	if !shardInfo.HasPrimary() {
		return fmt.Errorf("shard %v/%v has no primary", keyspace, shard)
	}
	alias := shardInfo.PrimaryAlias
	tabletInfo, err := wr.TopoServer().GetTablet(ctx, alias)
	if err != nil {
		return err
	}

	// Always run an explicit healthcheck first to make sure we don't see any outdated values.
	// This is especially true for tests and automation where there is no pause of multiple seconds
	// between commands and the periodic healthcheck did not run again yet.
	if err := wr.TabletManagerClient().RunHealthCheck(ctx, tabletInfo.Tablet); err != nil {
		return fmt.Errorf("failed to run explicit healthcheck on tablet: %v err: %v", tabletInfo, err)
	}

	conn, err := tabletconn.GetDialer()(ctx, tabletInfo.Tablet, grpcclient.FailFast(false))
	if err != nil {
		return fmt.Errorf("cannot connect to tablet %v: %v", alias, err)
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Complete primary initialization: `vtctldclient InitShardPrimary <keyspace/shard> <tablet-alias>` (or let the workflow's planned rebalance/primary election finish).
  2. Check `vtctldclient GetShard <keyspace>/<shard>` — primary_alias must be set — then re-run the wait.
  3. If the shard is genuinely headless (no primary intended), WaitForFilteredReplication cannot be used for it.

Example fix

// before
vtctldclient WaitForFilteredReplication customer/0 30s
// error: shard customer/0 has no primary
// after
vtctldclient InitShardPrimary customer/0 zone1-101
vtctldclient WaitForFilteredReplication customer/0 30s
Defensive patterns

Strategy: validation

Validate before calling

// Before waiting, ensure the shard has a primary
shardInfo, _ := vtctldclientGetShard(keyspace, shard)
if shardInfo.PrimaryAlias == nil || shardInfo.PrimaryAlias.Uid == 0 {
    // run InitShardPrimary first
    fmt.Printf("%s/%s has no primary; run InitShardPrimary\n", keyspace, shard)
}

Prevention

When it happens

Trigger: Calling WaitForFilteredReplication on a destination shard whose record lacks a primary — e.g. InitShardPrimary was never run on the new shard, or the primary was lost and the record cleared.

Common situations: Reshard workflow creating a new shard but primary election/InitShardPrimary not completed yet; running wait before tablets in the new shard were started and promoted.

Related errors


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