thanos-io/thanos · error
empty name for metric family
Error message
empty name for metric family
What it means
NewMetricFamilyMap builds a map from dto.MetricFamily pointers keyed by family name. Prometheus's Gather() output must never contain a family with an empty name; if it does, the helper refuses to build the map and returns this error as an internal invariant violation.
Solutions
- Audit registered Collectors for Collect methods that append MetricFamily values without setting Name.
- Identify the offending collector by testing with only standard collectors enabled and bisecting.
- Ensure metrics come from Gatherer.Gather() output rather than manually constructed slices.
- Upgrade Prometheus client_golang / collector libraries to a version fixing the empty-name bug.
Defensive patterns
Strategy: validation
Validate before calling
for _, mf := range families {
if mf.GetName() == "" {
return fmt.Errorf("metric family with empty name from collector")
}
}
err := util.NewMetricFamilyMap(families) Try / catch
mfm, err := util.NewMetricFamilyMap(metrics)
if err != nil {
level.Error(logger).Log("msg", "gather produced invalid metric families", "err", err)
return nil, err
} Prevention
- Only feed NewMetricFamilyMap with Gatherer.Gather() output.
- Test custom collectors with prometheus/client_golang's testutil.CollectAndCompare.
- Never construct dto.MetricFamily slices by hand without setting Name.
When it happens
Trigger: Passing a []*dto.MetricFamily containing an entry whose GetName() is empty to NewMetricFamilyMap — typically via softRemoveUserRegistry or BuildMetricFamiliesPerUser on a registry whose gatherer produced a nameless family.
Common situations: Buggy custom collectors registering metrics without names; corrupt or hand-assembled MetricFamily slices; third-party collector implementations violating the prometheus contract.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- non-unique name for metric family
- parsing metric families against
- metric families did not contain…
- could not calculate compaction progress
- could not calculate retention progress
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/ca97eee5d16433c6.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cortex/util/metrics_helper.go:77
out <- prometheus.MustNewConstMetric(desc, valueType, cr.Value, cr.LabelValues...)
}
}
// MetricFamilyMap is a map of metric names to their family (metrics with same name, but different labels)
// Keeping map of metric name to its family makes it easier to do searches later.
type MetricFamilyMap map[string]*dto.MetricFamily
// NewMetricFamilyMap sorts output from Gatherer.Gather method into a map.
// Gatherer.Gather specifies that there metric families are uniquely named, and we use that fact here.
// If they are not, this method returns error.
func NewMetricFamilyMap(metrics []*dto.MetricFamily) (MetricFamilyMap, error) {
perMetricName := MetricFamilyMap{}
for _, m := range metrics {
name := m.GetName()
// these errors should never happen when passing Gatherer.Gather() output.
if name == "" {
return nil, errors.New("empty name for metric family")
}
if perMetricName[name] != nil {
return nil, fmt.Errorf("non-unique name for metric family: %q", name)
}
perMetricName[name] = m
}
return perMetricName, nil
}
func (mfm MetricFamilyMap) SumCounters(name string) float64 {
return sum(mfm[name], counterValue)
}
func (mfm MetricFamilyMap) SumGauges(name string) float64 {
return sum(mfm[name], gaugeValue)
}View on GitHub (pinned to 35b8b99117)