{"record":{"id":"5aeaae0d1af296be","repo":"vitessio/vitess","slug":"duplicate-v-v-entry","errorCode":null,"errorMessage":"duplicate %v/%v entry","messagePattern":"duplicate (.+?)/(.+?) entry","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/discovery/topology_watcher.go","lineNumber":376,"sourceCode":"\tfor _, filter := range filters {\n\t\tparts := strings.Split(filter, \"|\")\n\t\tif len(parts) != 2 {\n\t\t\treturn nil, fmt.Errorf(\"invalid FilterByShard parameter: %v\", filter)\n\t\t}\n\n\t\tkeyspace := parts[0]\n\t\tshard := parts[1]\n\n\t\t// extract keyrange if it's a range\n\t\tcanonical, kr, err := topo.ValidateShardName(shard)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing shard name %v: %v\", shard, err)\n\t\t}\n\n\t\t// check for duplicates\n\t\tfor _, c := range m[keyspace] {\n\t\t\tif c.shard == canonical {\n\t\t\t\treturn nil, fmt.Errorf(\"duplicate %v/%v entry\", keyspace, shard)\n\t\t\t}\n\t\t}\n\n\t\tm[keyspace] = append(m[keyspace], &filterShard{\n\t\t\tkeyspace: keyspace,\n\t\t\tshard:    canonical,\n\t\t\tkeyRange: kr,\n\t\t})\n\t}\n\n\tfbs := &FilterByShard{\n\t\tfilters: m,\n\t\toptions: withOptions(opts...),\n\t}\n\n\treturn fbs, nil\n}\n","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/discovery/topology_watcher.go#L358-L394","documentation":"NewFilterByShard canonicalizes each shard name (keyranges are normalized) and rejects duplicate entries for the same keyspace with this error, since a duplicate filter shard adds nothing and likely signals a config mistake.","triggerScenarios":"Calling NewFilterByShard with two entries that canonicalize to the same keyspace+shard — exact duplicates like 'commerce|0' twice, or aliases like 'commerce|-' vs 'commerce|-80' when the keyspace has a single shard spanning the whole range.","commonSituations":"Repeating a filter in a long comma-separated tablet-filters list; combining a full-range filter with an explicit shard of the same keyspace; generated config scripts appending filters programmatically.","solutions":["Deduplicate the tablet-filters list, keeping one entry per keyspace|shard pair.","Remember canonicalization: a whole-range entry ('-') may collide with explicit boundaries in single-shard keyspaces — pick one form.","Run the list through NewFilterByShard (or a set keyed on keyspace+canonical shard) before writing the config.","Check the error's %v/%v values to identify the exact colliding keyspace and shard."],"exampleFix":"// before\nNewFilterByShard([]string{\"commerce|0\", \"commerce|0\"})\n// after\nNewFilterByShard([]string{\"commerce|0\"})","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, f := range filters {\n\tparts := strings.Split(f, \"|\")\n\tkey := parts[0] + \"|\" + parts[1]\n\tif seen[key] {\n\t\treturn fmt.Errorf(\"duplicate filter %s\", key)\n\t}\n\tseen[key] = true\n}","typeGuard":null,"tryCatchPattern":"fbs, err := discovery.NewFilterByShard(filters)\nif err != nil {\n\tlog.Exitf(\"duplicate entries in tablet-filters: %v\", err)\n}","preventionTips":["Deduplicate the filter list (after canonicalization) before configuring","Avoid mixing whole-range ('-') and explicit-boundary entries for the same keyspace","Build filter lists programmatically with a set to prevent repeats"],"tags":["configuration","parsing","discovery"],"backgroundTag":"invalid-config-value","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}