prometheus/node_exporter · error
couldn't get ce_count for controller/csrow
Error message
couldn't get ce_count for controller/csrow %s/%s: %w
What it means
After matching a csrow path, the EDAC collector reads <csrow>/ce_count with readUintFromFile and wraps any failure with this message, naming the controller and csrow numbers. The wrapped error carries the underlying reason (missing file, permission, non-numeric content). A failed read aborts the whole scrape of the EDAC collector.
Solutions
- Verify the file exists: `cat /sys/devices/system/edac/mc/mc0/csrow0/ce_count`.
- Check permissions/ownership of the sysfs csrow directories for the node_exporter user.
- Ensure the correct EDAC kernel module is loaded for your memory controller (e.g. amd64_edac, i7core_edac) so all standard attributes are exposed.
- Check for mid-scrape module unload races; pin module loading via modprobe config.
Example fix
// before: any read error aborts the collector
if err != nil {
return fmt.Errorf("couldn't get ce_count for controller/csrow %s/%s: %w", controllerNumber, csrowNumber, err)
}
// after (caller-side guard): pre-check the attribute
if _, err := os.Stat(csrowPath + "/ce_count"); os.IsNotExist(err) {
// disable edac collector or expect partial data
} Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require('fs');
for (const d of fs.existsSync('/sys/devices/system/edac/mc') ? fs.readdirSync('/sys/devices/system/edac/mc') : []) {
for (const c of fs.readdirSync(`/sys/devices/system/edac/mc/${d}`).filter(x => x.startsWith('csrow'))) {
const f = `/sys/devices/system/edac/mc/${d}/${c}/ce_count`;
if (!fs.existsSync(f) || isNaN(parseInt(fs.readFileSync(f, 'utf8'), 10))) {
console.warn(`edac ce_count unreadable: ${f} — disable --collector.edac`);
}
}
} Try / catch
try {
await scrapeNodeExporter();
} catch (e) {
if (String(e).includes('couldn\'t get ce_count')) {
console.warn('EDAC ce_count unreadable; disabling edac collector: --collector.edac=false');
} else throw e;
} Prevention
- Pre-check ce_count readability before enabling the edac collector.
- Ensure the exporter user can read /sys/devices/system/edac (deploy with read-only host /sys).
- Avoid unloading EDAC modules while node_exporter is scraping.
When it happens
Trigger: readUintFromFile(filepath.Join(csrow, "ce_count")) fails during Update: file absent, unreadable, or containing a non-integer value.
Common situations: Kernel EDAC driver exposing csrow dirs without ce_count (some drivers omit it); restrictive permissions after hardening; proc/sys fs mounted oddly in containers; transient removal of the csrow dir on module unload mid-scrape.
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
- couldn't get ce_count for controller
- couldn't get ce_noinfo_count for controller
- couldn't get ue_count for controller
- couldn't get ue_noinfo_count for controller
- couldn't get ue_count for controller/csrow
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/810ac20b48cc5057.
Report an issue: GitHub.
Appendix: source
Thrown at collector/edac_linux.go:154
}
ch <- prometheus.MustNewConstMetric(
edacCsRowUECount, prometheus.CounterValue, float64(value), controllerNumber, "unknown")
// For each controller, walk the csrow directories.
csrows, err := filepath.Glob(controller + "/csrow[0-9]*")
if err != nil {
return err
}
for _, csrow := range csrows {
csrowMatch := edacMemCsrowRE.FindStringSubmatch(csrow)
if csrowMatch == nil {
return fmt.Errorf("csrow string didn't match regexp: %s", csrow)
}
csrowNumber := csrowMatch[1]
value, err = readUintFromFile(filepath.Join(csrow, "ce_count"))
if err != nil {
return fmt.Errorf("couldn't get ce_count for controller/csrow %s/%s: %w", controllerNumber, csrowNumber, err)
}
ch <- prometheus.MustNewConstMetric(
edacCsRowCECount, prometheus.CounterValue, float64(value), controllerNumber, csrowNumber)
value, err = readUintFromFile(filepath.Join(csrow, "ue_count"))
if err != nil {
return fmt.Errorf("couldn't get ue_count for controller/csrow %s/%s: %w", controllerNumber, csrowNumber, err)
}
ch <- prometheus.MustNewConstMetric(
edacCsRowUECount, prometheus.CounterValue, float64(value), controllerNumber, csrowNumber)
channelFiles, err := filepath.Glob(csrow + "/ch*_ce_count")
if err != nil {
return err
}
for _, chFile := range channelFiles {
match := edacMemChannelRE.FindStringSubmatch(filepath.Base(chFile))
if match == nil {View on GitHub (pinned to 17ddd77c59)