prometheus/node_exporter · error
failed to open procfs
Error message
failed to open procfs: %w
What it means
NewXfrmCollector constructs a procfs.FS rooted at the --path.procfs flag and fails immediately if the filesystem cannot be opened/validated. The xfrm collector reads /proc/net/stat/xfrm_statistics via procfs; if the procfs mount point is inaccessible the collector constructor returns this wrapped error and the collector is never registered.
Solutions
- Verify the --path.procfs value points to a valid procfs mount (ls <path>/net/stat/xfrm_statistics must work).
- In containers, bind-mount the host's /proc (e.g. -v /proc:/host/proc:ro and --path.procfs=/host/proc).
- Ensure /proc is mounted before node_exporter starts (startup ordering / mount namespace setup).
- Since xfrm is disabled by default, simply don't enable it (--collector.xfrm) if not needed.
- Check permissions on the procfs path for the user running node_exporter.
Example fix
// before node_exporter --collector.xfrm --path.procfs=/host/proc # /host/proc not mounted // after docker run -v /proc:/host/proc:ro ... node_exporter --collector.xfrm --path.procfs=/host/proc
Defensive patterns
Strategy: validation
Validate before calling
// Go: validate the procfs root before constructing the collector
p := *procPath
if fi, err := os.Stat(filepath.Join(p, "net", "stat", "xfrm_statistics")); err != nil || fi.IsDir() {
// xfrm stats unavailable at this procfs path; don't enable the xfrm collector
}
if fi, err := os.Stat(p); err != nil || !fi.IsDir() {
log.Fatalf("procfs path %q is not a directory", p)
} Try / catch
coll, err := collector.NewXfrmCollector(logger)
if err != nil {
if strings.Contains(err.Error(), "failed to open procfs") {
logger.Warn("procfs unavailable; xfrm collector disabled", "err", err)
coll = nil
} else {
return err
}
} Prevention
- Always pass --path.procfs matching where /proc is actually mounted (especially in containers)
- Bind-mount host /proc read-only when running in Docker/Kubernetes
- Mount /proc before starting node_exporter in minimal/chroot environments
- Remember xfrm is disabled by default — only enable it on Linux hosts with /proc/net/stat/xfrm_statistics
When it happens
Trigger: procfs.NewFS(*procPath) fails because the path given by --path.procfs does not exist, is not a directory, or cannot be accessed — raised at collector construction time (also reproduced directly by TestXfrmStats in tests).
Common situations: Passing a wrong --path.procfs when running node_exporter in a container with a bind-mounted /proc at a different location, pointing procfs at a host mount that isn't mounted yet, running tests without a realistic /proc (the test uses a fixture path), chroot environments lacking /proc.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- failed to open procfs
- failed to open procfs
- failed to open procfs
- failed to open procfs
- interrupts empty
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/ae8967dcae52d74a.
Report an issue: GitHub.
Appendix: source
Thrown at collector/xfrm.go:39
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/procfs"
)
type xfrmCollector struct {
fs procfs.FS
logger *slog.Logger
}
func init() {
registerCollector("xfrm", defaultDisabled, NewXfrmCollector)
}
// NewXfrmCollector returns a new Collector exposing XFRM stats.
func NewXfrmCollector(logger *slog.Logger) (Collector, error) {
fs, err := procfs.NewFS(*procPath)
if err != nil {
return nil, fmt.Errorf("failed to open procfs: %w", err)
}
return &xfrmCollector{
fs: fs,
logger: logger,
}, nil
}
var (
xfrmInErrorDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "xfrm", "in_error_packets_total"),
"All errors not matched by other",
nil, nil,
)
xfrmInBufferErrorDesc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, "xfrm", "in_buffer_error_packets_total"),
"No buffer is left",
nil, nil,View on GitHub (pinned to 17ddd77c59)