vitessio/vitess · error

no primary in shard record %v/%v. Consider running 'vtctl In

Error message

no primary in shard record %v/%v. Consider running 'vtctl InitShardPrimary' in case of a new shard or reparenting the shard to fix the topology data, or providing a non-primary tablet alias

What it means

CopySchemaShardFromShard requires the source shard record to contain a PrimaryAlias so it can fetch the schema from the source primary. This error is returned when the shard record exists but has no primary assigned — the shard was never initialized as primary or is mid-reparent with stale topo data. The message suggests remediation via InitShardPrimary or reparenting.

Source

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

// PreflightSchema will try a schema change on the remote tablet.
func (wr *Wrangler) PreflightSchema(ctx context.Context, tabletAlias *topodatapb.TabletAlias, changes []string) ([]*tabletmanagerdatapb.SchemaChangeResult, error) {
	ti, err := wr.ts.GetTablet(ctx, tabletAlias)
	if err != nil {
		return nil, fmt.Errorf("GetTablet(%v) failed: %v", tabletAlias, err)
	}
	return wr.tmc.PreflightSchema(ctx, ti.Tablet, changes)
}

// CopySchemaShardFromShard copies the schema from a source shard to the specified destination shard.
// For both source and destination it picks the primary tablet. See also CopySchemaShard.
func (wr *Wrangler) CopySchemaShardFromShard(ctx context.Context, tables, excludeTables []string, includeViews bool, sourceKeyspace, sourceShard, destKeyspace, destShard string, waitReplicasTimeout time.Duration, skipVerify bool) error {
	sourceShardInfo, err := wr.ts.GetShard(ctx, sourceKeyspace, sourceShard)
	if err != nil {
		return fmt.Errorf("GetShard(%v, %v) failed: %v", sourceKeyspace, sourceShard, err)
	}
	if sourceShardInfo.PrimaryAlias == nil {
		return fmt.Errorf("no primary in shard record %v/%v. Consider running 'vtctl InitShardPrimary' in case of a new shard or reparenting the shard to fix the topology data, or providing a non-primary tablet alias", sourceKeyspace, sourceShard)
	}

	return wr.CopySchemaShard(ctx, sourceShardInfo.PrimaryAlias, tables, excludeTables, includeViews, destKeyspace, destShard, waitReplicasTimeout, skipVerify)
}

// CopySchemaShard copies the schema from a source tablet to the
// specified shard.  The schema is applied directly on the primary of
// the destination shard, and is propagated to the replicas through
// binlogs.
func (wr *Wrangler) CopySchemaShard(ctx context.Context, sourceTabletAlias *topodatapb.TabletAlias, tables, excludeTables []string, includeViews bool, destKeyspace, destShard string, waitReplicasTimeout time.Duration, skipVerify bool) error {
	destShardInfo, err := wr.ts.GetShard(ctx, destKeyspace, destShard)
	if err != nil {
		return fmt.Errorf("GetShard(%v, %v) failed: %v", destKeyspace, destShard, err)
	}

	if destShardInfo.PrimaryAlias == nil {
		return fmt.Errorf("no primary in shard record %v/%v. Consider running 'vtctl InitShardPrimary' in case of a new shard or reparenting the shard to fix the topology data", destKeyspace, destShard)
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Run vtctl InitShardPrimary <keyspace>/<shard> <tablet-alias> to assign a primary.
  2. Or run a PlannedReparentShard/ElectivityReparentShard to restore a primary.
  3. Alternatively pass a specific source tablet alias using CopySchemaShard instead of CopySchemaShardFromShard.
  4. Verify with vtctl GetShard that PrimaryAlias is set before retrying.

Example fix

// before (no primary)
wr.CopySchemaShardFromShard(ctx, nil, nil, true, "ks", "0", "ks", "-80", timeout, false)
// after: assign primary first, then copy
vtctl InitShardPrimary ks/0 cell1-0000000100
wr.CopySchemaShardFromShard(ctx, nil, nil, true, "ks", "0", "ks", "-80", timeout, false)
Defensive patterns

Strategy: validation

Validate before calling

si, err := ts.GetShard(ctx, sourceKeyspace, sourceShard)
if err != nil { return err }
if si.PrimaryAlias == nil {
	return fmt.Errorf("source shard %s/%s has no primary; run InitShardPrimary first", sourceKeyspace, sourceShard)
}

Type guard

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

Try / catch

err := wr.CopySchemaShardFromShard(...)
if err != nil && strings.Contains(err.Error(), "no primary in shard record") {
	// remediate via vtctl InitShardPrimary or use CopySchemaShard with an explicit alias
}

Prevention

When it happens

Trigger: Calling CopySchemaShardFromShard against a shard whose topology record has PrimaryAlias == nil: freshly created shard never primaried, shard whose primary was lost and not yet re-elected, or corrupted/stale topo data after a reparent.

Common situations: New shard created with CreateKeyspace but InitShardPrimary never run; failed reparent left the shard record without a primary; disaster recovery where the primary cell data was lost.

Related errors


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