vitessio/vitess · error

CreateShard(%v, %v): %w

Error message

CreateShard(%v, %v): %w

What it means

CopyShards wraps errors from toTS.CreateShard(ctx, keyspace, shard) with the keyspace and shard names. This is the first destination-side write: NodeExists on the destination is expected and downgraded to a warning; any other error (connection failure, permission, timeout) aborts the copy.

Source

Thrown at go/vt/topo/helpers/copy.go:101

	}

	for _, keyspace := range keyspaces {
		shards, err := fromTS.GetShardNames(ctx, keyspace)
		if err != nil {
			return fmt.Errorf("GetShardNames(%v): %w", keyspace, err)
		}

		for _, shard := range shards {
			si, err := fromTS.GetShard(ctx, keyspace, shard)
			if err != nil {
				return fmt.Errorf("GetShard(%v, %v): %w", keyspace, shard, err)
			}

			if err := toTS.CreateShard(ctx, keyspace, shard); err != nil {
				if topo.IsErrType(err, topo.NodeExists) {
					log.Warn(fmt.Sprintf("shard %v/%v already exists", keyspace, shard))
				} else {
					return fmt.Errorf("CreateShard(%v, %v): %w", keyspace, shard, err)
				}
			}
			if _, err := toTS.UpdateShardFields(ctx, keyspace, shard, func(toSI *topo.ShardInfo) error {
				toSI.Shard = si.CloneVT()
				return nil
			}); err != nil {
				return fmt.Errorf("UpdateShardFields(%v, %v): %w", keyspace, shard, err)
			}
		}
	}

	return nil
}

// CopyTablets will create the tablets in the destination topo.
func CopyTablets(ctx context.Context, fromTS, toTS *topo.Server) error {
	cells, err := fromTS.GetKnownCells(ctx)
	if err != nil {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check destination topo (toTS) connectivity and that the backend accepts writes.
  2. Verify write ACLs/credentials for the destination topo user.
  3. If the error is an unexpected non-NodeExists conflict, inspect the destination shard node and reconcile manually.
  4. Retry the copy after fixing the destination; existing shards are skipped safely.

Example fix

// before
if err := toTS.CreateShard(ctx, keyspace, shard); err != nil {
	if topo.IsErrType(err, topo.NodeExists) {
		log.Warn(fmt.Sprintf("shard %v/%v already exists", keyspace, shard))
	} else {
		return fmt.Errorf("CreateShard(%v, %v): %w", keyspace, shard, err)
	}
}
// after (caller verifies destination is writable first)
err := toTS.CreateKeyspace(ctx, probeKs, &topodatapb.Keyspace{})
if err != nil && !topo.IsErrType(err, topo.NodeExists) {
	return fmt.Errorf("destination topo not writable: %w", err)
}
_ = toTS.DeleteKeyspace(ctx, probeKs)
Defensive patterns

Strategy: validation

Validate before calling

err := toTS.CreateKeyspace(ctx, probeKs, &topodatapb.Keyspace{})
writable := err == nil || topo.IsErrType(err, topo.NodeExists)
if err == nil {
	_ = toTS.DeleteKeyspace(ctx, probeKs)
}
_ = writable

Try / catch

if err := toTS.CreateShard(ctx, keyspace, shard); err != nil && !topo.IsErrType(err, topo.NodeExists) {
	if topo.IsErrType(err, topo.PermissionDenied) {
		return fmt.Errorf("fix destination topo write ACLs: %w", err)
	}
	return fmt.Errorf("CreateShard(%v, %v): %w", keyspace, shard, err)
}

Prevention

When it happens

Trigger: Calling CopyShards when the destination topo rejects CreateShard for reasons other than NodeExists: destination topo unreachable, write ACL denied, or context canceled during the create RPC.

Common situations: Destination etcd/zk cluster read-only (e.g. etcd in maintenance, zk read-only mode); missing write credentials in destination topo config; network partition to the destination cluster mid-copy.

Related errors


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