vitessio/vitess · error

no primary in shard %v/%v

Error message

no primary in shard %v/%v

What it means

ValidatePermissionsShard validates that all tablets in a shard share consistent permissions by comparing against the primary's permissions. If the shard has no primary (HasPrimary() is false in the topo), validation cannot proceed and this error is reported.

Source

Thrown at go/vt/wrangler/permissions.go:68

		er.RecordError(err)
		return
	}

	log.Info(fmt.Sprintf("Diffing permissions for %v", topoproto.TabletAliasString(alias)))
	tmutils.DiffPermissions(topoproto.TabletAliasString(primaryAlias), primaryPermissions, topoproto.TabletAliasString(alias), replicaPermissions, er)
}

// ValidatePermissionsShard validates all the permissions are the same
// in a shard
func (wr *Wrangler) ValidatePermissionsShard(ctx context.Context, keyspace, shard string) error {
	si, err := wr.ts.GetShard(ctx, keyspace, shard)
	if err != nil {
		return err
	}

	// get permissions from the primary, or error
	if !si.HasPrimary() {
		return fmt.Errorf("no primary in shard %v/%v", keyspace, shard)
	}
	log.Info(fmt.Sprintf("Gathering permissions for primary %v", topoproto.TabletAliasString(si.PrimaryAlias)))
	primaryPermissions, err := wr.GetPermissions(ctx, si.PrimaryAlias)
	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)
	if err != nil {
		return err
	}

	// then diff all of them, except primary
	er := concurrency.AllErrorRecorder{}
	wg := sync.WaitGroup{}
	for _, alias := range aliases {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Elect a primary: `vtctldclient PlannedReparentShard <keyspace>/<shard> --new-primary=<alias>`
  2. Confirm with `vtctldclient GetShard <keyspace>/<shard>` that PrimaryAlias is set, then re-run validation
  3. If the shard genuinely should not have a primary, skip validation for that shard

Example fix

// before
vtctldclient ValidatePermissionsShard commerce/0   # no primary
// after
vtctldclient PlannedReparentShard commerce/0 --new-primary=zone1-101
vtctldclient ValidatePermissionsShard commerce/0
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("cannot validate permissions: no primary in %s/%s", keyspace, shard)
}

Type guard

func hasPrimary(si *topo.ShardInfo) bool { return si != nil && si.HasPrimary() }

Try / catch

if err := wr.ValidatePermissionsShard(ctx, keyspace, shard); err != nil {
    if strings.Contains(err.Error(), "no primary in shard") {
        // reparent the shard or skip it in the validation loop
    }
}

Prevention

When it happens

Trigger: Running `vtctldclient ValidatePermissionsShard <keyspace>/<shard>` or ValidatePermissionsKeyspace against a shard whose ShardInfo lacks PrimaryAlias — e.g. no elected primary, primary just reparented and topo not updated, or a shard of an externally-managed keyspace.

Common situations: Auditing permissions after a failed reparent; shard with only replica/rdonly tablets; stale topo after primary deletion.

Related errors


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