{"record":{"id":"3cf2265ebc08424c","repo":"vitessio/vitess","slug":"updateshardfields-v-v-w","errorCode":null,"errorMessage":"UpdateShardFields(%v, %v): %w","messagePattern":"UpdateShardFields\\((.+?), (.+?)\\): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/topo/helpers/copy.go","lineNumber":108,"sourceCode":"\n\t\tfor _, shard := range shards {\n\t\t\tsi, err := fromTS.GetShard(ctx, keyspace, shard)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"GetShard(%v, %v): %w\", keyspace, shard, err)\n\t\t\t}\n\n\t\t\tif err := toTS.CreateShard(ctx, keyspace, shard); err != nil {\n\t\t\t\tif topo.IsErrType(err, topo.NodeExists) {\n\t\t\t\t\tlog.Warn(fmt.Sprintf(\"shard %v/%v already exists\", keyspace, shard))\n\t\t\t\t} else {\n\t\t\t\t\treturn fmt.Errorf(\"CreateShard(%v, %v): %w\", keyspace, shard, err)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif _, err := toTS.UpdateShardFields(ctx, keyspace, shard, func(toSI *topo.ShardInfo) error {\n\t\t\t\ttoSI.Shard = si.CloneVT()\n\t\t\t\treturn nil\n\t\t\t}); err != nil {\n\t\t\t\treturn fmt.Errorf(\"UpdateShardFields(%v, %v): %w\", keyspace, shard, err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// CopyTablets will create the tablets in the destination topo.\nfunc CopyTablets(ctx context.Context, fromTS, toTS *topo.Server) error {\n\tcells, err := fromTS.GetKnownCells(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fromTS.GetKnownCells: %w\", err)\n\t}\n\n\tfor _, cell := range cells {\n\t\ttabletAliases, err := fromTS.GetTabletAliasesByCell(ctx, cell)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"GetTabletsByCell(%v): %w\", cell, err)","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/topo/helpers/copy.go#L90-L126","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif _, err := toTS.UpdateShardFields(ctx, keyspace, shard, func(toSI *topo.ShardInfo) error {\n\ttoSI.Shard = si.CloneVT()\n\treturn nil\n}); err != nil {\n\treturn fmt.Errorf(\"UpdateShardFields(%v, %v): %w\", keyspace, shard, err)\n}\n// after (bounded retry)\nerr := retry.Do(func() error {\n\t_, e := toTS.UpdateShardFields(ctx, keyspace, shard, func(toSI *topo.ShardInfo) error {\n\t\ttoSI.Shard = si.CloneVT()\n\t\treturn nil\n\t})\n\treturn e\n}, retry.Attempts(3))\nif err != nil {\n\treturn fmt.Errorf(\"UpdateShardFields(%v, %v): %w\", keyspace, shard, err)\n}","handlingStrategy":"retry","validationCode":"_, err := toTS.GetShard(ctx, ks, shard)\nif err != nil && !topo.IsErrType(err, topo.NodeExists) {\n\treturn fmt.Errorf(\"destination shard missing and unreadable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"_, err := toTS.UpdateShardFields(ctx, keyspace, shard, updateFn)\nif err != nil {\n\tif topo.IsErrType(err, topo.NoNode) {\n\t\t// recreate shard then retry the update\n\t}\n\treturn fmt.Errorf(\"UpdateShardFields(%v, %v): %w\", keyspace, shard, err)\n}","preventionTips":["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."],"tags":["go","topo","transaction"],"backgroundTag":"topo-update-conflict","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}