vitessio/vitess · error

no primary in shard %v/%v

Error message

no primary in shard %v/%v

What it means

ValidateSchemaShard requires a primary tablet in the shard to serve as the schema baseline; this error is returned when the shard record shows no primary (si.HasPrimary() is false). Schema validation cannot proceed without a source of truth for the schema.

Source

Thrown at go/vt/wrangler/schema.go:66

	if err != nil {
		er.RecordError(fmt.Errorf("GetSchema(%v, nil, %v, %v) failed: %v", alias, excludeTables, includeViews, err))
		return
	}

	log.Info(fmt.Sprintf("Diffing schema for %v", topoproto.TabletAliasString(alias)))
	tmutils.DiffSchema(topoproto.TabletAliasString(primaryTabletAlias), primarySchema, topoproto.TabletAliasString(alias), replicaSchema, er)
}

// ValidateSchemaShard will diff the schema from all the tablets in the shard.
func (wr *Wrangler) ValidateSchemaShard(ctx context.Context, keyspace, shard string, excludeTables []string, includeViews bool, includeVSchema bool) error {
	si, err := wr.ts.GetShard(ctx, keyspace, shard)
	if err != nil {
		return fmt.Errorf("GetShard(%v, %v) failed: %v", keyspace, shard, err)
	}

	// get schema from the primary, or error
	if !si.HasPrimary() {
		return fmt.Errorf("no primary in shard %v/%v", keyspace, shard)
	}
	log.Info(fmt.Sprintf("Gathering schema for primary %v", topoproto.TabletAliasString(si.PrimaryAlias)))
	req := &tabletmanagerdatapb.GetSchemaRequest{ExcludeTables: excludeTables, IncludeViews: includeViews}
	primarySchema, err := schematools.GetSchema(ctx, wr.ts, wr.tmc, si.PrimaryAlias, req)
	if err != nil {
		return fmt.Errorf("GetSchema(%v, nil, %v, %v) failed: %v", si.PrimaryAlias, excludeTables, includeViews, err)
	}

	if includeVSchema {
		err := wr.ValidateVSchema(ctx, keyspace, []string{shard}, excludeTables, includeViews)
		if err != nil {
			return err
		}
	}

	// read all the aliases in the shard, that is all tablets that are
	// replicating from the primary
	aliases, err := wr.ts.FindAllTabletAliasesInShard(ctx, keyspace, shard)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Run vtctldclient PlannedReparentShard (or EmergencyReparentShard) to elect a primary and populate PrimaryAlias
  2. If no valid primary candidate exists, add a tablet and use InitShardPrimary --force
  3. Verify shard state with vtctldclient GetShard <keyspace/shard> before validating
  4. Ensure tablet health checks are passing so reparenting can succeed

Example fix

// before: shard has no primary
// after: elect a primary
vtctldclient PlannedReparentShard commerce/0 commerce-0000000100
Defensive patterns

Strategy: validation

Validate before calling

si, err := ts.GetShard(ctx, keyspace, shard)
if err != nil { return err }
if !si.HasPrimary() {
    return fmt.Errorf("shard %s/%s has no primary; reparent first", keyspace, shard)
}

Type guard

func shardHasPrimary(ctx context.Context, ts topoclient.Server, keyspace, shard string) bool {
    si, err := ts.GetShard(ctx, keyspace, shard)
    return err == nil && si.HasPrimary()
}

Try / catch

if err := wr.ValidateSchemaShard(ctx, ks, shard, nil, true, false); err != nil {
    if strings.Contains(err.Error(), "no primary in shard") {
        // trigger PlannedReparentShard before retrying
    }
}

Prevention

When it happens

Trigger: Running ValidateSchemaShard on a shard whose Shard record has no PrimaryAlias — e.g. during reparenting, after a failed InitShardPrimary, or in an empty/decommissioned shard.

Common situations: Primary tablet was down so an emergency reparent left the shard record without a primary; shard was created but tablets never initialized; scripted decommission removed the primary; aborted planned reparenting.

Related errors


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