vitessio/vitess · error

shard: %s does not have a primary

Error message

shard: %s does not have a primary

What it means

During TabletExecutor.Open, the executor lists all shards of the keyspace and refuses to proceed if any shard has no primary tablet. Vitess cannot run schema management against a shard without an elected primary.

Source

Thrown at go/vt/schemamanager/tablet_executor.go:123

// hasProvidedUUIDs returns true when UUIDs were provided
func (exec *TabletExecutor) hasProvidedUUIDs() bool {
	return len(exec.uuids) != 0
}

// Open opens a connection to the primary for every shard.
func (exec *TabletExecutor) Open(ctx context.Context, keyspace string) error {
	if !exec.isClosed {
		return nil
	}
	exec.keyspace = keyspace
	shards, err := exec.ts.FindAllShardsInKeyspace(ctx, keyspace, nil)
	if err != nil {
		return fmt.Errorf("unable to get shards for keyspace: %s, error: %v", keyspace, err)
	}
	exec.tablets = make([]*topodatapb.Tablet, 0, len(shards))
	for shardName, shardInfo := range shards {
		if !shardInfo.HasPrimary() {
			return fmt.Errorf("shard: %s does not have a primary", shardName)
		}
		tabletInfo, err := exec.ts.GetTablet(ctx, shardInfo.PrimaryAlias)
		if err != nil {
			return fmt.Errorf("unable to get primary tablet info, keyspace: %s, shard: %s, error: %v", keyspace, shardName, err)
		}
		exec.tablets = append(exec.tablets, tabletInfo.Tablet)
	}

	if len(exec.tablets) == 0 {
		return fmt.Errorf("keyspace: %s does not contain any primary tablets", keyspace)
	}
	exec.isClosed = false
	return nil
}

// Validate validates a list of sql statements.
func (exec *TabletExecutor) Validate(ctx context.Context, sqls []string) error {
	if exec.isClosed {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Fix replication on the affected shard: run `vttablet`/`vtctl InitShardPrimary` (or PlannedReparentShard) to elect a primary
  2. Verify shard state with `vtctl GetShard <keyspace>/<shard>` and confirm PrimaryAlias is set
  3. If the shard should not exist, remove it with `vtctl DeleteShard` or correct the keyspace targeted by the schema operation
  4. Retry the schema application once all shards have primaries

Example fix

// before: applying schema to keyspace with empty shard
vtctlclient ApplySchema -sql "..." commerce
// after: ensure primary exists first, or prune empty shards
vtctlclient RemoveKeyspace -recursive empty_ks
vtctlclient ApplySchema -sql "..." commerce
Defensive patterns

Strategy: validation

Validate before calling

shards, err := ts.GetShardMap(ctx, keyspace)
if err != nil { return err }
for name, info := range shards {
    if !info.HasPrimary() {
        return fmt.Errorf("shard %s has no primary; fix topology before ApplySchema", name)
    }
}

Type guard

func shardHasPrimary(s *topodatapb.Shard) bool {
    return s != nil && s.PrimaryAlias != nil && s.PrimaryAlias.Uid != 0
}

Try / catch

if err := executor.Open(ctx, keyspace); err != nil {
    if strings.Contains(err.Error(), "does not have a primary") {
        return fmt.Errorf("keyspace %s not ready for schema change: %w", keyspace, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling schemamanager (e.g. ApplySchema via tablet_executor) when one or more shards of the target keyspace lack a primary (ShardInfo.HasPrimary() == false), typically after a failed primary election or an empty/disabled keyspace.

Common situations: Running ApplySchema on a keyspace with a shard still in orphaned state, a shard whose primary alias was pruned by the new shard pruning policy, or during resharding when the target shard has no primary yet.

Related errors


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