{"record":{"id":"a3e9eca44060ce90","repo":"vitessio/vitess","slug":"mismatched-shards-for-keyspace-s-s","errorCode":null,"errorMessage":"mismatched shards for keyspace %s: %s","messagePattern":"mismatched shards for keyspace (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/workflow/utils.go","lineNumber":522,"sourceCode":"\t}\n\n\ttopoShardSet := sets.New[string](topoShards...)\n\tif !shardSet.Equal(topoShardSet) {\n\t\twfExtra := shardSet.Difference(topoShardSet)\n\t\ttopoExtra := topoShardSet.Difference(shardSet)\n\n\t\tvar rec concurrency.AllErrorRecorder\n\t\tif wfExtra.Len() > 0 {\n\t\t\twfExtraSorted := sets.List(wfExtra)\n\t\t\trec.RecordError(fmt.Errorf(\"switch command shards not in topo: %v\", wfExtraSorted))\n\t\t}\n\n\t\tif topoExtra.Len() > 0 {\n\t\t\ttopoExtraSorted := sets.List(topoExtra)\n\t\t\trec.RecordError(fmt.Errorf(\"topo shards not in switch command: %v\", topoExtraSorted))\n\t\t}\n\n\t\treturn fmt.Errorf(\"mismatched shards for keyspace %s: %s\", keyspace, strings.Join(rec.ErrorStrings(), \"; \"))\n\t}\n\n\treturn nil\n}\n\n// HashStreams produces a stable hash based on the target keyspace and migration\n// targets.\nfunc HashStreams(targetKeyspace string, targets map[string]*MigrationTarget) int64 {\n\tvar expanded []string\n\tfor shard, target := range targets {\n\t\tfor uid := range target.Sources {\n\t\t\texpanded = append(expanded, fmt.Sprintf(\"%s:%d\", shard, uid))\n\t\t}\n\t}\n\n\tsort.Strings(expanded)\n\n\thasher := fnv.New64()","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/workflow/utils.go#L504-L540","documentation":"This is the aggregate error CompareShards returns when either side (switch command or topo) had extra shards. It joins all recorded shard-set differences into one message keyed by keyspace so the operator sees the full mismatch at once. Validation of the switch operation aborts when this is returned.","triggerScenarios":"Any SwitchTraffic (or similar validated workflow command) whose -shards set differs from the topo shard set for the keyspace — the two more-specific errors (not in topo / not in switch command) are wrapped into this summary error.","commonSituations":"Same as the specific mismatches: stale shard lists, typo'd ranges, partial cutovers; the operator often sees only this summary line first.","solutions":["Read the semicolon-separated detail after the colon; it lists the exact extra shards on each side.","Fix the -shards list to exactly equal the topo shard set for the keyspace.","Re-run after any reshard/merge so the command reflects the current shard layout."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check set equality\nif !sets.New[string](shards...).Equal(sets.New[string](topoShardsForKeyspace(ks)...)) {\n    return fmt.Errorf(\"shard set mismatch for %s\", ks)\n}","typeGuard":null,"tryCatchPattern":"if err := validate(ks, shards); err != nil {\n    if strings.HasPrefix(err.Error(), \"mismatched shards for keyspace\") {\n        // print details and fetch the authoritative shard list\n        log.Warn(\"shard mismatch\", slog.Any(\"error\", err))\n        shards = topoShardsForKeyspace(ks)\n    }\n    return err\n}","preventionTips":["Treat the topo as the source of truth for shard lists.","Log and inspect the semicolon-separated details in the message.","Rehearse switch commands in staging to catch stale lists."],"tags":["go","topology","sharding","validation"],"backgroundTag":"shard-set-mismatch","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}