prometheus/node_exporter · error
failed to open /proc/self
Error message
failed to open /proc/self: %w
What it means
After opening procfs, NewNetStatCollector calls fs.Self() to obtain a handle on /proc/self so netstat data is read from the current process's network namespace. If procfs cannot resolve /proc/self, the constructor returns this wrapped error and the collector fails to initialize.
Solutions
- Ensure /proc/self exists and is readable by the exporter process (ls -l /proc/self).
- Check proc mount options; relax hidepid or run the exporter with sufficient privileges.
- In containers, mount a full /proc rather than a partial subset.
- Verify with --path.procfs that the configured procfs root actually contains the self entry.
Example fix
// before
proc, err := fs.Self()
if err != nil {
return nil, fmt.Errorf("failed to open /proc/self: %w", err)
}
// after (add path context for debugging)
proc, err := fs.Self()
if err != nil {
return nil, fmt.Errorf("failed to open /proc/self under %q (check hidepid/container proc mount): %w", *procPath, err)
} Defensive patterns
Strategy: validation
Validate before calling
import "os"
// Ensure /proc/self is resolvable under the configured procfs root:
if _, err := os.Stat(*procPath + "/self"); err != nil {
// /proc/self missing: check proc mount completeness/hidepid before init
} Type guard
null
Try / catch
// Constructor-time handling: fail fast with actionable context
if _, err := NewNetStatCollector(logger); err != nil {
if strings.Contains(err.Error(), "/proc/self") {
logger.Error("procfs self-entry unreadable; check hidepid and container mounts", "err", err)
}
return err
} Prevention
- Avoid hidepid=2 on hosts running node_exporter, or grant access via supplementary groups.
- Mount a complete /proc in containers, not a partial directory tree.
- Verify /proc/self resolves at startup (readlink /proc/self).
- Use the same mount namespace for the exporter and the procfs it reads.
When it happens
Trigger: fs.Self() fails when /proc/self cannot be read or resolved, e.g. /proc is mounted but lacks the self symlink, or the process's procfs entries are hidden/unreadable (hidepid, restricted containers).
Common situations: Containers mounting a partial /proc; hidepid=2 proc mounts restricting access; chroot/minimal images without a fully populated procfs.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/f95963d08b8a9b11.
Report an issue: GitHub.
Appendix: source
Thrown at collector/netstat_linux.go:69
func init() {
registerCollector("netstat", defaultEnabled, NewNetStatCollector)
}
// NewNetStatCollector takes and returns
// a new Collector exposing network stats.
func NewNetStatCollector(logger *slog.Logger) (Collector, error) {
pattern := regexp.MustCompile(*netStatFields)
fs, err := procfs.NewFS(*procPath)
if err != nil {
return nil, fmt.Errorf("failed to open procfs: %w", err)
}
// Network statistics in /proc/net are network namespace local. Reading
// them via the current process' /proc/self/net keeps the same semantics
// while allowing the use of the procfs parsers.
proc, err := fs.Self()
if err != nil {
return nil, fmt.Errorf("failed to open /proc/self: %w", err)
}
return &netStatCollector{
proc: proc,
fieldPattern: pattern,
logger: logger,
}, nil
}
func (c *netStatCollector) Update(ch chan<- prometheus.Metric) error {
netStats, err := c.proc.Netstat()
if err != nil {
return fmt.Errorf("couldn't get netstats: %w", err)
}
snmpStats, err := c.proc.Snmp()
if err != nil {
return fmt.Errorf("couldn't get SNMP stats: %w", err)
}View on GitHub (pinned to 17ddd77c59)