vitessio/vitess · error
UpdateShardFields(%v, %v): %w
Error message
UpdateShardFields(%v, %v): %w
What it means
CopyShards wraps errors from toTS.UpdateShardFields(ctx, keyspace, shard, updateFn) with the keyspace and shard names. After creating (or finding existing) the destination shard, the copy overwrites the destination Shard record with a clone of the source shard via a read-modify-write transaction. Failure here means the shard exists in the destination but its contents could not be synced, aborting the copy.
Source
Thrown at go/vt/topo/helpers/copy.go:108
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 {
return fmt.Errorf("fromTS.GetKnownCells: %w", err)
}
for _, cell := range cells {
tabletAliases, err := fromTS.GetTabletAliasesByCell(ctx, cell)
if err != nil {
return fmt.Errorf("GetTabletsByCell(%v): %w", cell, err)View on GitHub (pinned to 01a25a7d17)
Solutions
- Retry the copy — CreateShard tolerates NodeExists and UpdateShardFields will re-apply the source shard content.
- If the wrapped cause is NoNode on the destination, check what deleted the shard concurrently (vtctld jobs, other migrations).
- Check destination topo backend latency/health; increase context deadline.
- Re-run only for affected keyspaces/shards; the message names them exactly.
Example fix
// before
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)
}
// after (bounded retry)
err := retry.Do(func() error {
_, e := toTS.UpdateShardFields(ctx, keyspace, shard, func(toSI *topo.ShardInfo) error {
toSI.Shard = si.CloneVT()
return nil
})
return e
}, retry.Attempts(3))
if err != nil {
return fmt.Errorf("UpdateShardFields(%v, %v): %w", keyspace, shard, err)
} Defensive patterns
Strategy: retry
Validate before calling
_, err := toTS.GetShard(ctx, ks, shard)
if err != nil && !topo.IsErrType(err, topo.NodeExists) {
return fmt.Errorf("destination shard missing and unreadable: %w", err)
} Try / catch
_, err := toTS.UpdateShardFields(ctx, keyspace, shard, updateFn)
if err != nil {
if topo.IsErrType(err, topo.NoNode) {
// recreate shard then retry the update
}
return fmt.Errorf("UpdateShardFields(%v, %v): %w", keyspace, shard, err)
} Prevention
- Prevent concurrent tools from mutating destination shards during the copy.
- Use bounded retries on UpdateShardFields for transient backend errors.
- Size the context deadline for the number of shards being updated.
When it happens
Trigger: Calling CopyShards when UpdateShardFields fails: destination topo connection error during the update transaction, the destination shard node deleted concurrently mid-update (NoNode), or context canceled during the call.
Common situations: Another tool concurrently deleting/rewriting shards in the destination topo; destination etcd/zk timeouts under load; flaky network to the destination during long batch copies.
Related errors
- cells alias %v is not valid: %v
- cell set overlaps with existing alias %v
- unknown topo protobuf type for %v
- GetKeyspaces: %w
- GetKeyspace(%v): %w
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/3cf2265ebc08424c.
Report an issue: GitHub.