prometheus/node_exporter · error

couldn't get ce_count for controller

Error message

couldn't get ce_count for controller %s: %w

What it means

After matching a controller directory, Update reads its ce_count attribute via readUintFromFile. Any failure (missing file, permission, non-numeric content) aborts the scrape wrapped with the controller number. This indicates the EDAC sysfs attributes for that controller are unreadable or absent.

Solutions

  1. Check the file exists and is readable: cat /sys/devices/system/edac/memctlr/mc0/ce_count
  2. Run node_exporter with enough privileges to read EDAC attributes
  3. Check the wrapped (%w) cause to distinguish ENOENT from EACCES or parse errors
  4. Verify the EDAC driver exposes correctable-error counters; if not, the collector cannot report them

Example fix

// before
node_exporter (unprivileged, EACCES on ce_count)
// after
sudo node_exporter  # or relax permissions on /sys/devices/system/edac/memctlr/*/ce_count
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.ReadFile("/sys/devices/system/edac/memctlr/mc0/ce_count"); err != nil {
    // ce_count unreadable; run exporter as root or relax permissions
}

Try / catch

if err := c.Update(ch); err != nil {
    if strings.Contains(err.Error(), "couldn't get ce_count") {
        // inspect wrapped cause: ENOENT (driver lacks it) vs EACCES (permissions)
    }
}

Prevention

When it happens

Trigger: readUintFromFile(<controller>/ce_count) fails: the file does not exist for this EDAC driver, permissions deny read, or the content cannot be parsed as a uint.

Common situations: EDAC drivers that omit ce_count; running node_exporter without root when ce_count is root-only; kernels where the attribute was renamed/removed across versions.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at collector/edac_linux.go:114

	label = strings.ReplaceAll(label, "channel", "_channel")
	return label
}

func (c *edacCollector) Update(ch chan<- prometheus.Metric) error {
	memControllers, err := filepath.Glob(sysFilePath("devices/system/edac/mc/mc[0-9]*"))
	if err != nil {
		return err
	}
	for _, controller := range memControllers {
		controllerMatch := edacMemControllerRE.FindStringSubmatch(controller)
		if controllerMatch == nil {
			return fmt.Errorf("controller string didn't match regexp: %s", controller)
		}
		controllerNumber := controllerMatch[1]

		value, err := readUintFromFile(filepath.Join(controller, "ce_count"))
		if err != nil {
			return fmt.Errorf("couldn't get ce_count for controller %s: %w", controllerNumber, err)
		}
		ch <- prometheus.MustNewConstMetric(
			edacCeCount, prometheus.CounterValue, float64(value), controllerNumber)

		value, err = readUintFromFile(filepath.Join(controller, "ce_noinfo_count"))
		if err != nil {
			return fmt.Errorf("couldn't get ce_noinfo_count for controller %s: %w", controllerNumber, err)
		}
		ch <- prometheus.MustNewConstMetric(
			edacCsRowCECount, prometheus.CounterValue, float64(value), controllerNumber, "unknown")

		value, err = readUintFromFile(filepath.Join(controller, "ue_count"))
		if err != nil {
			return fmt.Errorf("couldn't get ue_count for controller %s: %w", controllerNumber, err)
		}
		ch <- prometheus.MustNewConstMetric(
			edacUeCount, prometheus.CounterValue, float64(value), controllerNumber)

View on GitHub (pinned to 17ddd77c59)