{"record":{"id":"e0a1800f15f3ad51","repo":"prometheus/node_exporter","slug":"failed-to-open-procfs-w-e0a180","errorCode":null,"errorMessage":"failed to open procfs: %w","messagePattern":"failed to open procfs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"collector/entropy_linux.go","lineNumber":52,"sourceCode":"\nvar (\n\tentropyAvail = prometheus.NewDesc(\n\t\tprometheus.BuildFQName(namespace, \"\", \"entropy_available_bits\"),\n\t\t\"Bits of available entropy.\",\n\t\tnil, nil,\n\t)\n\tentropyPoolSize = prometheus.NewDesc(\n\t\tprometheus.BuildFQName(namespace, \"\", \"entropy_pool_size_bits\"),\n\t\t\"Bits of entropy pool.\",\n\t\tnil, nil,\n\t)\n)\n\n// NewEntropyCollector returns a new Collector exposing entropy stats.\nfunc NewEntropyCollector(logger *slog.Logger) (Collector, error) {\n\tfs, err := procfs.NewFS(*procPath)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to open procfs: %w\", err)\n\t}\n\n\treturn &entropyCollector{\n\t\tfs:     fs,\n\t\tlogger: logger,\n\t}, nil\n}\n\nfunc (c *entropyCollector) Update(ch chan<- prometheus.Metric) error {\n\tstats, err := c.fs.KernelRandom()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get kernel random stats: %w\", err)\n\t}\n\n\tif stats.EntropyAvaliable == nil {\n\t\treturn fmt.Errorf(\"couldn't get entropy_avail\")\n\t}\n\tch <- prometheus.MustNewConstMetric(","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/entropy_linux.go#L34-L70","documentation":"The entropy collector's constructor calls procfs.NewFS(*procPath) (default /proc). If the configured path cannot be opened as a procfs filesystem, node_exporter fails to create the collector and reports 'failed to open procfs'. NewFS validates the path exists and looks like procfs, so this is almost always a bad --path.procfs flag or an environment where /proc is missing.","triggerScenarios":"NewEntropyCollector with --path.procfs pointing at a nonexistent or non-procfs directory; running in a container without /proc mounted.","commonSituations":"Typo in --path.procfs; containers/chroots lacking /proc; running the binary in an environment where procfs is mounted elsewhere; SELinux restricting access.","solutions":["Verify the flag: `--path.procfs=/proc` and that the directory exists (`ls /proc`).","Mount proc in the container: run with a proper /proc mount (docker does this by default; check overridden volumes).","If procfs lives elsewhere, point the flag at the actual mount point.","Check mount/permission errors: the wrapped error (%w) names the real cause — read it."],"exampleFix":"// before: bad path\nnode_exporter --path.procfs=/prco\n\n// after\nnode_exporter --path.procfs=/proc","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nfunction procfsLooksValid(p = '/proc') {\n  return fs.existsSync(p) && fs.statSync(p).isDirectory() &&\n    fs.existsSync(`${p}/self`) && fs.existsSync(`${p}/sys/kernel/random`);\n}\nif (!procfsLooksValid()) console.error('--path.procfs target invalid; entropy collector will fail to start');","typeGuard":null,"tryCatchPattern":"try {\n  await startNodeExporter({ procPath: '/proc' });\n} catch (e) {\n  if (String(e).includes('failed to open procfs')) {\n    console.error('Bad --path.procfs; verify the mount and flag value');\n  } else throw e;\n}","preventionTips":["Always pass --path.procfs=/proc explicitly in deployment configs.","In containers, never override the default /proc mount; bind-mount host /proc if namespace isolation hides it.","Smoke-test the exact flag values in CI before rollout."],"tags":["linux","procfs","configuration","startup"],"backgroundTag":"invalid-config-value","analyzedSha":"17ddd77c59ba27e1508e9f7894b1e55b44d6aed3","analyzedAt":"2026-09-07T17:54:06.211Z","contentChangedAt":"2026-09-07T17:54:06.211Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}