vitessio/vitess · error

source shard must have a primary for copying schema: %v

Error message

source shard must have a primary for copying schema: %v

What it means

During MoveTables/LiveMigration schema copy, the materializer must fetch the source table DDLs from a source shard's primary tablet. This error is thrown by getSourceTableDDLs when the first source shard has no PrimaryAlias, meaning Vitess does not know of a serving primary in that shard, so schema cannot be copied.

Source

Thrown at go/vt/wrangler/materializer.go:1137

	return &materializer{
		wr:                    wr,
		ms:                    ms,
		targetVSchema:         targetVSchema,
		sourceShards:          sourceShards,
		targetShards:          targetShards,
		isPartial:             isPartial,
		primaryVindexesDiffer: differentPVs,
	}, nil
}

func (mz *materializer) getSourceTableDDLs(ctx context.Context) (map[string]string, error) {
	sourceDDLs := make(map[string]string)
	allTables := []string{"/.*/"}

	sourcePrimary := mz.sourceShards[0].PrimaryAlias
	if sourcePrimary == nil {
		return nil, fmt.Errorf("source shard must have a primary for copying schema: %v", mz.sourceShards[0].ShardName())
	}

	ti, err := mz.wr.sourceTs.GetTablet(ctx, sourcePrimary)
	if err != nil {
		return nil, err
	}
	req := &tabletmanagerdatapb.GetSchemaRequest{Tables: allTables}
	sourceSchema, err := mz.wr.tmc.GetSchema(ctx, ti.Tablet, req)
	if err != nil {
		return nil, err
	}

	for _, td := range sourceSchema.TableDefinitions {
		sourceDDLs[td.Name] = td.Schema
	}
	return sourceDDLs, nil
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Ensure the source shard has a healthy primary: run `vtctldclient PlannedReparentShard <keyspace>/<shard>` or PromoteReplica to elect one
  2. Wait for the topology to reflect the new primary and re-run the workflow
  3. If the source keyspace cannot have a primary, provide an explicit CreateDdl statement per table instead of 'copy'
  4. Check `vtctldclient GetShard <keyspace>/<shard>` to confirm PrimaryAlias is set before starting the workflow

Example fix

// before (vtctldclient)
vtctldclient MoveTables --target-keyspace=commerce create --source-keyspace=inventory --tables='t1'
// after: first ensure a primary exists
vtctldclient GetShard commerce/0        # verify PrimaryAlias
vtctldclient PlannedReparentShard commerce/0 --new-primary=zone1-101
vtctldclient MoveTables --target-keyspace=commerce create --source-keyspace=inventory --tables='t1'
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Prevention

When it happens

Trigger: Running a materialization workflow (MoveTables, Reshard-backed materialization) with stopWorld or schema copy where the source keyspace's first shard has no elected primary — e.g. source keyspace is externally managed, primary is down/reparenting, or the shard has only replica/rdonly tablets.

Common situations: User points materialization at a source keyspace whose primary was just failed over and topo not yet updated; source keyspace left without a primary after disaster recovery; table CreateDdl set to 'copy' so deploySchema lazily calls getSourceTableDDLs on a primary-less shard.

Related errors


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