{"record":{"id":"2732e49c96e134d8","repo":"vitessio/vitess","slug":"gaugeswithmultilabels-wrong-number-of-values-in-s","errorCode":null,"errorMessage":"GaugesWithMultiLabels: wrong number of values in Set","messagePattern":"GaugesWithMultiLabels: wrong number of values in Set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/stats/counters.go","lineNumber":392,"sourceCode":"\t\tlabels: labels,\n\t}\n\tif name != \"\" {\n\t\tpublish(name, t)\n\t}\n\n\treturn t\n}\n\n// GetLabelName returns a label name using the provided values.\nfunc (mg *GaugesWithMultiLabels) GetLabelName(names ...string) string {\n\treturn safeJoinLabels(names, nil)\n}\n\n// Set sets the value of a named counter.\n// len(names) must be equal to len(Labels).\nfunc (mg *GaugesWithMultiLabels) Set(names []string, value int64) {\n\tif len(names) != len(mg.labels) {\n\t\tpanic(\"GaugesWithMultiLabels: wrong number of values in Set\")\n\t}\n\tmg.set(safeJoinLabels(names, nil), value)\n}\n\n// ResetKey resets a specific key.\n//\n// It is the equivalent of `Reset(names)` except that it expects the key to\n// be obtained from the internal counters map.\n//\n// This is useful when you range over all internal counts and you want to reset\n// specific keys.\nfunc (mg *GaugesWithMultiLabels) ResetKey(key string) {\n\tmg.set(key, 0)\n}\n\n// GaugesFuncWithMultiLabels is a wrapper around CountersFuncWithMultiLabels\n// for values that go up/down for implementations (like Prometheus) that\n// need to differ between Counters and Gauges.","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/stats/counters.go#L374-L410","documentation":"GaugesWithMultiLabels.Set panics when the names slice length doesn't match the number of labels the gauge was created with. The gauge joins names into a flat key (with no combined labels), so arity must match the declared labels exactly to produce a valid metric key.","triggerScenarios":"Calling mg.Set(names, value) with len(names) != len(mg.labels). The known caller updateTableIndexMetrics passes label values derived from table metadata; if the gauge's label definition and that call site diverge, this panics.","commonSituations":"Vindex/table-governor metrics where the label set changed (e.g. adding a keyspace label) but one side wasn't updated; dynamic names built from optional metadata fields.","solutions":["Ensure the Set call passes exactly one value per declared label, in order","Sync updateTableIndexMetrics (or your caller) with the gauge's label definition after any metric schema change","Validate/skip with a warning when label values can't be fully populated instead of passing a short slice"],"exampleFix":"// before\nmg.Set([]string{table}, 1) // gauge declares [keyspace, table] -> panics\n// after\nmg.Set([]string{keyspace, table}, 1)","handlingStrategy":"validation","validationCode":"if len(names) == len(mg.Labels()) {\n    mg.Set(names, value)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep updateTableIndexMetrics and the gauge definition in the same file/PR scope","Build label slices from the declared label list, not ad-hoc literals","Skip-and-log when metadata can't supply all labels"],"tags":["go","panic","stats","metrics","gauge"],"backgroundTag":"label-arity-mismatch","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}