{"record":{"id":"d27005691d1e99bd","repo":"henrygd/beszel","slug":"no-sysfs-values-found","errorCode":null,"errorMessage":"no sysfs values found","messagePattern":"no sysfs values found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"agent/gpu_intel_sysfs_linux.go","lineNumber":268,"sourceCode":"\treturn strconv.ParseUint(strings.TrimSpace(val), 10, 64)\n}\n\nfunc readOptionalSysfsFloat(path string) (float64, error) {\n\tval, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn strconv.ParseFloat(strings.TrimSpace(string(val)), 64)\n}\n\nfunc readFirstOptionalSysfsFloat(paths ...string) (float64, error) {\n\tfor _, path := range paths {\n\t\tval, err := readOptionalSysfsFloat(path)\n\t\tif err == nil {\n\t\t\treturn val, nil\n\t\t}\n\t}\n\treturn 0, fmt.Errorf(\"no sysfs values found\")\n}\n\nfunc getIntelSysfsGpuName(cardPath string) string {\n\tdevicePath := filepath.Join(cardPath, \"device\")\n\tif product, err := utils.ReadStringFileLimited(filepath.Join(devicePath, \"product_name\"), 128); err == nil && strings.TrimSpace(product) != \"\" {\n\t\treturn strings.TrimSpace(product)\n\t}\n\tif name, err := utils.ReadStringFileLimited(filepath.Join(devicePath, \"name\"), 128); err == nil && strings.TrimSpace(name) != \"\" {\n\t\treturn strings.TrimSpace(name)\n\t}\n\treturn fmt.Sprintf(\"Intel GPU %s\", filepath.Base(cardPath))\n}\n","sourceCodeStart":250,"sourceCodeEnd":281,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/agent/gpu_intel_sysfs_linux.go#L250-L281","documentation":"The Intel sysfs GPU collector's readFirstOptionalSysfsFloat iterates candidate sysfs value paths and fails when none of them can be read. It means the Intel GPU metrics files (e.g. frequency/energy counters) were absent or unreadable at every expected path.","triggerScenarios":"updateIntelSysfsGpuData calls readFirstOptionalSysfsFloat(paths); every readOptionalSysfsFloat(path) call errors (file missing, permission denied, invalid contents), so the loop exits and returns 'no sysfs values found'.","commonSituations":"Running in a container without /sys mounted or with restricted device access; non-Intel GPU or iGPU without the expected hwmon/drm metric nodes; kernel version exposing different sysfs layout; cardPath guessed wrong when enumerating /sys/class/drm/card*.","solutions":["Mount /sys and the GPU devices into the container (--device /dev/dri, bind-mount /sys/class/drm and /sys/devices).","Run the agent with permissions to read the sysfs nodes (root or appropriate group, e.g. video/render).","Verify the expected files exist: ls /sys/class/drm/card0/device/hwmon/*/ and drm node metrics.","Update the agent/kernel — sysfs layout varies across kernels; newer beszel versions support more paths.","Treat as non-fatal if other GPU metrics (name, temp) still work; this metric is simply skipped."],"exampleFix":"// before\ndocker run beszel/agent\n// after\ndocker run --device /dev/dri --volume /sys:/sys:ro beszel/agent","handlingStrategy":"try-catch","validationCode":"// precondition check for Intel sysfs metrics:\nls /sys/class/drm/card*/device/hwmon/*/ 2>/dev/null || echo 'no hwmon nodes'\n[ -d /sys/class/drm ] || echo 'sysfs not mounted'","typeGuard":null,"tryCatchPattern":"val, err := readFirstOptionalSysfsFloat(paths)\nif err != nil {\n    slog.Debug(\"optional GPU metric unavailable\", \"err\", err)\n    val = 0 // metric skipped, other GPU data still reported\n}","preventionTips":["Mount /sys (read-only) and /dev/dri into containers","Run the agent as root or in the video/render group","Pin recent kernels/agent versions since sysfs layouts change","Treat optional metrics as best-effort and alert on total GPU data loss instead"],"tags":["gpu","linux","sysfs","intel"],"backgroundTag":"sysfs-node-missing","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}