{"record":{"id":"477cc391e6be5a12","repo":"prometheus/node_exporter","slug":"error-obtaining-pci-device-info-w","errorCode":null,"errorMessage":"error obtaining PCI device info: %w","messagePattern":"error obtaining PCI device info: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/pcidevice_linux.go","lineNumber":206,"sourceCode":"\t\t\tprometheus.BuildFQName(namespace, pcideviceSubsystem, \"info\"),\n\t\t\t\"Non-numeric data from /sys/bus/pci/devices/<location>, value is always 1.\",\n\t\t\tlabelNames,\n\t\t\tnil,\n\t\t),\n\t\tvalueType: prometheus.GaugeValue,\n\t}\n\n\treturn c, nil\n}\n\nfunc (c *pcideviceCollector) Update(ch chan<- prometheus.Metric) error {\n\tdevices, err := c.fs.PciDevices()\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\tc.logger.Debug(\"PCI device not found, skipping\")\n\t\t\treturn ErrNoData\n\t\t}\n\t\treturn fmt.Errorf(\"error obtaining PCI device info: %w\", err)\n\t}\n\n\tfor _, device := range devices {\n\t\t// The device location is represented in separated format.\n\t\tvalues := device.Location.Strings()\n\t\tif device.ParentLocation != nil {\n\t\t\tvalues = append(values, device.ParentLocation.Strings()...)\n\t\t} else {\n\t\t\tvalues = append(values, []string{\"*\", \"*\", \"*\", \"*\"}...)\n\t\t}\n\n\t\t// Add basic device information\n\t\tclassID := fmt.Sprintf(\"0x%06x\", device.Class)\n\t\tvendorID := fmt.Sprintf(\"0x%04x\", device.Vendor)\n\t\tdeviceID := fmt.Sprintf(\"0x%04x\", device.Device)\n\t\tsubsysVendorID := fmt.Sprintf(\"0x%04x\", device.SubsystemVendor)\n\t\tsubsysDeviceID := fmt.Sprintf(\"0x%04x\", device.SubsystemDevice)\n","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/pcidevice_linux.go#L188-L224","documentation":"Update enumerates PCI devices with c.fs.PciDevices(). ErrNotExist is downgraded to a debug log + ErrNoData, but any other error is wrapped as \"error obtaining PCI device info\" and fails the scrape. This signals an unexpected failure while reading PCI device attributes from sysfs, distinct from simply having no PCI info available.","triggerScenarios":"c.fs.PciDevices() returns a non-ErrNotExist error: permission/IO failures reading /sys/bus/pci/devices entries, readlink or attribute-read errors (e.g. EIO, EACCES variants not matching the check), malformed device directories in a test fixture root.","commonSituations":"Failing PCI hardware producing EIO during attribute reads; containers where most of sysfs is masked and reads return unusual errors; partially-populated test fixtures; kernel changes altering expected sysfs layout handled upstream in procfs/sysfs.","solutions":["Inspect the wrapped cause (%w) in the scrape error to identify the failing file/syscall","Re-scrape after fixing underlying I/O problems; check dmesg for PCI hardware errors","Ensure the process has read access to /sys/bus/pci/devices (avoid over-aggressive LSM/masked paths)","Fix or regenerate test fixtures if running against a truncated sysfs fixture root","If PCI info is genuinely absent, verify why ErrNotExist path isn't taken (path exists but is unreadable)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(filepath.Join(*sysPath, \"bus\", \"pci\", \"devices\")); err != nil || !fi.IsDir() { log.Println(\"pci devices dir unreadable\") }","typeGuard":"func pciDevicesReadable(sysPath string) bool {\n    f, err := os.Open(filepath.Join(sysPath, \"bus\", \"pci\", \"devices\"))\n    if err != nil { return false }\n    f.Close()\n    return true\n}","tryCatchPattern":"if err := c.Update(ch); err != nil {\n    if strings.Contains(err.Error(), \"error obtaining PCI device info\") {\n        logger.Warn(\"PCI scrape failed; skipping this cycle\", \"err\", err)\n        return nil // next scrape may succeed\n    }\n    return err\n}","preventionTips":["Do not mask /sys/bus/pci in container security policies if PCI metrics are needed","Treat repeated EIO-based failures as hardware alerts (check dmesg/lspci)","Keep the sysfs/procfs library current to track kernel sysfs layout changes","Regenerate test fixtures when sysfs layout in tests drifts"],"tags":["linux","sysfs","pci","scrape"],"backgroundTag":"file-read-failed","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"}