prometheus/node_exporter · error

device-exclude & device-include are mutually exclusive

Error message

device-exclude & device-include are mutually exclusive

What it means

NewNetDevCollector rejects startup when both --collector.netdev.device-exclude and --collector.netdev.device-include are set. The two flags express opposite filter intents, so combining them is ambiguous and refused at construction time.

Solutions

  1. Remove one of the two flags: keep device-include for allow-listing or device-exclude for deny-listing.
  2. Merge the intent into a single regex, e.g. device-include='^(eth0|eth1)$' instead of exclude plus include.
  3. Restart node_exporter with the corrected flag set and verify with --collector.netdev.device-include only.

Example fix

// before
node_exporter --collector.netdev.device-exclude='^lo$' --collector.netdev.device-include='^eth0$'
// after
node_exporter --collector.netdev.device-include='^eth0$'
Defensive patterns

Strategy: validation

Validate before calling

if cfg.NetdevDeviceExclude != "" && cfg.NetdevDeviceInclude != "" {
    return fmt.Errorf("netdev: set only one of device-exclude or device-include")
}

Prevention

When it happens

Trigger: Calling NewNetDevCollector (i.e., starting node_exporter) with non-empty values for both the netdev device-exclude flag and the netdev device-include flag.

Common situations: Operators migrating from an old config that had device-exclude and adding a new device-include without removing the old flag; copied command lines that accumulated both flags over time.

Understand the failure class

Background: "mutually exclusive" flag errors: what "can't supply both nx and xx", "--raw is not compatible with -i" and "cannot be used with" mean, and how to fix them — this error's family across 29 libraries.

Related errors


AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07). Data as JSON: /api/errors/d28f74bb982cc481. Report an issue: GitHub.

Appendix: source

Thrown at collector/netdev_common.go:74

		if *netdevDeviceInclude == "" {
			logger.Warn("--collector.netdev.device-whitelist is DEPRECATED and will be removed in 2.0.0, use --collector.netdev.device-include")
			*netdevDeviceInclude = *oldNetdevDeviceInclude
		} else {
			return nil, errors.New("--collector.netdev.device-whitelist and --collector.netdev.device-include are mutually exclusive")
		}
	}

	if *oldNetdevDeviceExclude != "" {
		if *netdevDeviceExclude == "" {
			logger.Warn("--collector.netdev.device-blacklist is DEPRECATED and will be removed in 2.0.0, use --collector.netdev.device-exclude")
			*netdevDeviceExclude = *oldNetdevDeviceExclude
		} else {
			return nil, errors.New("--collector.netdev.device-blacklist and --collector.netdev.device-exclude are mutually exclusive")
		}
	}

	if *netdevDeviceExclude != "" && *netdevDeviceInclude != "" {
		return nil, errors.New("device-exclude & device-include are mutually exclusive")
	}

	if *netdevDeviceExclude != "" {
		logger.Info("Parsed flag --collector.netdev.device-exclude", "flag", *netdevDeviceExclude)
	}

	if *netdevDeviceInclude != "" {
		logger.Info("Parsed Flag --collector.netdev.device-include", "flag", *netdevDeviceInclude)
	}

	return &netDevCollector{
		subsystem:    "network",
		deviceFilter: newDeviceFilter(*netdevDeviceExclude, *netdevDeviceInclude),
		metricDescs:  map[string]*prometheus.Desc{},
		logger:       logger,
	}, nil
}

View on GitHub (pinned to 17ddd77c59)