{"record":{"id":"a39e6e2335509777","repo":"prometheus/node_exporter","slug":"line-scan-did-not-return-2-fields-s","errorCode":null,"errorMessage":"line scan did not return 2 fields: %s","messagePattern":"line scan did not return 2 fields: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/meminfo_numa_linux.go","lineNumber":172,"sourceCode":"\t}\n\n\treturn memInfo, scanner.Err()\n}\n\nfunc parseMemInfoNumaStat(r io.Reader, nodeNumber string) ([]meminfoMetric, error) {\n\tvar (\n\t\tnumaStat []meminfoMetric\n\t\tscanner  = bufio.NewScanner(r)\n\t)\n\n\tfor scanner.Scan() {\n\t\tline := strings.TrimSpace(scanner.Text())\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tparts := strings.Fields(line)\n\t\tif len(parts) != 2 {\n\t\t\treturn nil, fmt.Errorf(\"line scan did not return 2 fields: %s\", line)\n\t\t}\n\n\t\tfv, err := strconv.ParseFloat(parts[1], 64)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid value in numastat: %w\", err)\n\t\t}\n\n\t\tnumaStat = append(numaStat, meminfoMetric{parts[0] + \"_total\", prometheus.CounterValue, nodeNumber, fv})\n\t}\n\treturn numaStat, scanner.Err()\n}\n","sourceCodeStart":154,"sourceCodeEnd":184,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/meminfo_numa_linux.go#L154-L184","documentation":"This error is returned by parseMemInfoNumaStat in collector/meminfo_numa_linux.go:172 when a non-empty line from /sys/devices/system/node/nodeN/numastat splits into a number of whitespace-separated fields other than exactly 2. The numastat format is 'stat_name value'; any deviation (extra columns, merged tokens) aborts parsing for that node.","triggerScenarios":"parseMemInfoNumaStat reads a non-empty line whose strings.Fields result has length != 2, e.g. 'hit 100 extra' or 'hit' (single field), from a node numastat file.","commonSituations":"Custom or patched kernels adding columns to numastat; virtualized environments exposing nonstandard numastat files; corrupted or fixture files used in tests; locale/whitespace oddities is unlikely but merged tokens can occur.","solutions":["Inspect /sys/devices/system/node/node*/numastat for the line with unexpected column count","Verify kernel version; if numastat gained columns, update the parser to select the expected fields","Re-read the file to rule out truncated reads racing with kernel updates","Rebuild with -tags nomeminfo_numa to disable this collector on affected platforms","Report the nonstandard numastat format upstream if a stock kernel produces it"],"exampleFix":"// before\nparts := strings.Fields(line)\nif len(parts) != 2 {\n\treturn nil, fmt.Errorf(\"line scan did not return 2 fields: %s\", line)\n}\n// after (tolerate extra columns by taking first two)\nparts := strings.Fields(line)\nif len(parts) < 2 {\n\treturn nil, fmt.Errorf(\"line scan did not return 2 fields: %s\", line)\n}","handlingStrategy":"validation","validationCode":"// Validate numastat line has exactly 2 fields before parsing\nparts := strings.Fields(line)\nif len(parts) != 2 {\n\treturn fmt.Errorf(\"expected 2 fields, got %d in %q\", len(parts), line)\n}","typeGuard":null,"tryCatchPattern":"_, err := parseMemInfoNumaStat(f, node)\nif err != nil {\n\tif strings.Contains(err.Error(), \"line scan did not return 2 fields\") {\n\t\t// degrade gracefully: skip numastat metrics, keep base meminfo\n\t}\n\treturn err\n}","preventionTips":["Verify `cat /sys/devices/system-node/*/numastat` format after kernel upgrades","Run e2e tests (make test-e2e) on target platforms before rollout","Avoid patched kernels that alter numastat layout without updating the parser","Alert on node_exporter scrape failures to detect format regressions"],"tags":["linux","sysfs","parsing","numastat","numa"],"backgroundTag":"invalid-argument-format","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"}