prometheus/node_exporter · error
missing collector
Error message
missing collector: %s
What it means
NewNodeCollector validates every filter name against the collectorState registry and returns "missing collector: <name>" when the requested collector name does not exist. This is a pure configuration error: the name was never a known collector (typo, renamed collector, or platform-specific collector absent on this OS/build). NewNodeCollector is called by innerHandler for each scrape, so a bad --collectors.enable/--collectors.disable filter fails the request.
Solutions
- Check the spelling against the collector list in `node_exporter --help-long` or README collector table
- Remove or correct the unknown name in the scrape URL query (e.g. /metrics?collectors.enable[]=buddyinfo) or enable/disable flags
- Diff collector names between the old and new node_exporter version after an upgrade
- Guard dynamically-built collector lists by validating each name against collectorState before calling NewNodeCollector
Example fix
// before
c, err := collector.NewNodeCollector(logger, filters...) // filter "memory-stats" -> missing collector
// after
valid := map[string]bool{"cpu": true, "memory": true, "diskstats": true}
filters = keepIf(filters, func(f string) bool { return valid[f] })
c, err := collector.NewNodeCollector(logger, filters...) Defensive patterns
Strategy: validation
Validate before calling
for _, f := range filters {
if _, ok := knownCollectors[f]; !ok {
return fmt.Errorf("unknown collector %q; see node_exporter --help-long", f)
}
} Try / catch
c, err := collector.NewNodeCollector(logger, filters...)
if err != nil {
if strings.HasPrefix(err.Error(), "missing collector:") {
return fmt.Errorf("config error: %w", err) // fail fast, fix config
}
return err
} Prevention
- Copy collector names only from --help-long or the README table, never by memory
- After upgrading node_exporter, diff collector names before applying scrape configs
- Per-OS: validate Linux-only collector names are absent on other platforms
- Keep scrape-config collector lists under review/version control
When it happens
Trigger: Passing filters such as NewNodeCollector(logger, "cpu-stats") (typo for "cpu"), enabling a collector removed/renamed in a newer node_exporter version, or requesting a Linux-only collector (e.g. "bcache") on non-Linux where collectorState lacks it.
Common situations: Typos in prometheus scrape config relabeling of ?collectors.enable[]; upgrade to a node_exporter version where a collector was renamed or deleted; copy-pasting collector lists between OS platforms; e2e scripts matching flags on the wrong OS.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- disabled collector
- collector returned no data
- --collector.diskstats.ignored-devices and…
- device-exclude & device-include are mutually exclusive
- --collector.filesystem.ignored-mount-points and…
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/e49e782b6b9af3f2.
Report an issue: GitHub.
Appendix: source
Thrown at collector/collector.go:111
// collectorFlagAction generates a new action function for the given collector
// to track whether it has been explicitly enabled or disabled from the command line.
// A new action function is needed for each collector flag because the ParseContext
// does not contain information about which flag called the action.
// See: https://github.com/alecthomas/kingpin/issues/294
func collectorFlagAction(collector string) func(ctx *kingpin.ParseContext) error {
return func(_ *kingpin.ParseContext) error {
forcedCollectors[collector] = true
return nil
}
}
// NewNodeCollector creates a new NodeCollector.
func NewNodeCollector(logger *slog.Logger, filters ...string) (*NodeCollector, error) {
f := make(map[string]bool)
for _, filter := range filters {
enabled, exist := collectorState[filter]
if !exist {
return nil, fmt.Errorf("missing collector: %s", filter)
}
if !*enabled {
return nil, fmt.Errorf("disabled collector: %s", filter)
}
f[filter] = true
}
collectors := make(map[string]Collector)
initiatedCollectorsMtx.Lock()
defer initiatedCollectorsMtx.Unlock()
for key, enabled := range collectorState {
if !*enabled || (len(f) > 0 && !f[key]) {
continue
}
if collector, ok := initiatedCollectors[key]; ok {
collectors[key] = collector
} else {
collector, err := factories[key](logger.With("collector", key))
if err != nil {View on GitHub (pinned to 17ddd77c59)