{"record":{"id":"ec55bb55148b8e1b","repo":"vitessio/vitess","slug":"invalid-filterbyshard-parameter-v","errorCode":null,"errorMessage":"invalid FilterByShard parameter: %v","messagePattern":"invalid FilterByShard parameter: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/discovery/topology_watcher.go","lineNumber":361,"sourceCode":"// a keyspace.\ntype filterShard struct {\n\tkeyspace string\n\tshard    string\n\tkeyRange *topodatapb.KeyRange // only set if shard is also a KeyRange\n\toptions  Options\n}\n\n// NewFilterByShard creates a new FilterByShard for use by a\n// TopologyWatcher. Each filter is a keyspace|shard entry, where shard\n// can either be a shard name, or a keyrange. All tablets that match\n// at least one keyspace|shard tuple will be forwarded by the\n// TopologyWatcher to its consumer.\nfunc NewFilterByShard(filters []string, opts ...Option) (*FilterByShard, error) {\n\tm := make(map[string][]*filterShard)\n\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","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/discovery/topology_watcher.go#L343-L379","documentation":"NewFilterByShard parses each filter entry by splitting on '|'. An entry that doesn't yield exactly two parts (keyspace|shard) is rejected with this error. It is the underlying parse error wrapped by the tablet-filters error in NewVTGateHealthCheckFilters.","triggerScenarios":"Calling NewFilterByShard (directly or via NewVTGateHealthCheckFilters) with an entry containing zero or multiple '|' separators — e.g. \"commerce\", \"commerce|0|extra\", or an empty string.","commonSituations":"Using dot or slash separators out of habit (\"commerce.0\", \"commerce/0\"); pasting fully-qualified table names or cell|keyspace|shard triples into tablet-filters; whitespace or empty entries in a comma-split list.","solutions":["Rewrite the offending entry as exactly 'keyspace|shard', e.g. 'commerce|0' or 'commerce|-'.","Use '-' as the shard name for a single-shard keyspace ('commerce|-').","Check for accidental extra '|' segments (cell-qualified values are not accepted here).","Trim whitespace/empty entries from the tablet-filters list before parsing."],"exampleFix":"// before\nNewFilterByShard([]string{\"commerce.0\"})\n// after\nNewFilterByShard([]string{\"commerce|0\"})","handlingStrategy":"validation","validationCode":"func validTabletFilter(f string) bool {\n\tparts := strings.Split(f, \"|\")\n\treturn len(parts) == 2 && parts[0] != \"\"\n}","typeGuard":null,"tryCatchPattern":"fbs, err := discovery.NewFilterByShard(filters)\nif err != nil {\n\tlog.Exitf(\"bad tablet-filters: %v\", err)\n}","preventionTips":["Always use '|' as the separator, exactly one per entry","Reject entries with extra '|' segments during config validation","Trim whitespace and drop empty entries before parsing"],"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"}