vitessio/vitess · error
mismatched cutoff and label lengths
Error message
mismatched cutoff and label lengths
What it means
NewGenericHistogram requires the labels slice to be exactly one longer than the cutoffs slice: one label per cutoff bucket plus a final label that captures everything above the highest cutoff. The library panics immediately when the counts do not satisfy this invariant.
Source
Thrown at go/stats/histogram.go:61
// based on the cutoffs. The buckets are categorized using the
// following criterion: cutoff[i-1] < value <= cutoff[i]. Anything
// higher than the highest cutoff is labeled as "inf".
func NewHistogram(name, help string, cutoffs []int64) *Histogram {
labels := make([]string, len(cutoffs)+1)
for i, v := range cutoffs {
labels[i] = strconv.FormatInt(v, 10)
}
labels[len(labels)-1] = "inf"
return NewGenericHistogram(name, help, cutoffs, labels, "Count", "Total")
}
// NewGenericHistogram creates a histogram where all the labels are
// supplied by the caller. The number of labels has to be one more than
// the number of cutoffs because the last label captures everything that
// exceeds the highest cutoff.
func NewGenericHistogram(name, help string, cutoffs []int64, labels []string, countLabel, totalLabel string) *Histogram {
if len(cutoffs) != len(labels)-1 {
panic("mismatched cutoff and label lengths")
}
h := &Histogram{
name: name,
help: help,
cutoffs: cutoffs,
labels: labels,
countLabel: countLabel,
totalLabel: totalLabel,
buckets: make([]atomic.Int64, len(labels)),
}
if name != "" {
publish(name, h)
}
return h
}
// Adds a hook that will be called every time a new value is added to the histogram
func (h *Histogram) AddHook(hook func(int64)) {View on GitHub (pinned to 01a25a7d17)
Solutions
- Make len(labels) == len(cutoffs)+1, with the last label the overflow bucket (commonly "unlimited").
- Recount the arrays at the call site; ensure every new cutoff gets a matching label plus keep the final catch-all label.
- Define cutoffs and labels together as a single paired constant/slice to avoid drift.
Example fix
// before
cutoffs := []int64{1, 10, 100}
labels := []string{"0-1", "1-10", "10-100"} // panics: missing catch-all
// after
labels := []string{"0-1", "1-10", "10-100", "unlimited"} Defensive patterns
Strategy: validation
Validate before calling
if len(labels) != len(cutoffs)+1 {
return fmt.Errorf("histogram %s: need %d labels, got %d", name, len(cutoffs)+1, len(labels))
}
h := stats.NewGenericHistogram(name, help, cutoffs, labels, countLabel, totalLabel) Prevention
- Define cutoffs and the trailing catch-all label together in one constant block.
- Include the overflow label (e.g. "unlimited") whenever you add a cutoff.
- Add a package-level test asserting label count for every predefined histogram.
When it happens
Trigger: Calling stats.NewGenericHistogram(name, help, cutoffs, labels, ...) with len(cutoffs) != len(labels)-1, e.g. 4 cutoffs with 4 or 6 labels.
Common situations: Hand-editing a cutoffs list without updating labels; generating labels programmatically and off-by-one; copying a predefined label set but trimming the catch-all last label.
Related errors
- CountersWithMultiLabels: wrong number of values in Add
- CountersWithMultiLabels: wrong number of values in Reset
- GaugesWithMultiLabels: wrong number of values in Set
- You've already registered a function
- nil not allowed
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/f01032aaefa221cc.
Report an issue: GitHub.