prometheus/node_exporter · error
did not parse a single
Error message
did not parse a single %q metric
What it means
parseProcfsFile finished reading the ZFS kstat file for the given format but parsed zero metrics from it, so the parser returns this error rather than silently producing nothing. This fires when the file is empty, has no `name type data` header, or all lines were skipped — e.g. truncated output or a changed file layout.
Solutions
- Check the kstat file content directly, e.g. `cat /proc/spl/kstat/zfs/arcstats`, confirming the `name type data` header and data rows exist.
- Verify the ZFS module is fully loaded (not mid-load) and the file is populated.
- Compare the file layout with the ZFS version node_exporter expects; upgrade the exporter for newer ZFS formats.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at collector/zfs_linux.go:250 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/e0c568a73f0092f9.
Report an issue: GitHub.
Appendix: source
Thrown at collector/zfs_linux.go:250
// TODO: when other KSTAT_DATA_* types arrive, much of this will need to be restructured
key := fmt.Sprintf("kstat.zfs.misc.%s.%s", fmtExt, parts[0])
switch parts[1] {
case kstatDataUint64:
value, err := strconv.ParseUint(parts[2], 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected unsigned integer value for %q: %w", key, err)
}
handler(zfsSysctl(key), value)
case kstatDataInt64:
value, err := strconv.ParseInt(parts[2], 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected signed integer value for %q: %w", key, err)
}
handler(zfsSysctl(key), value)
}
}
if !parseLine {
return fmt.Errorf("did not parse a single %q metric", fmtExt)
}
return scanner.Err()
}
func (c *zfsCollector) parsePoolProcfsFile(reader io.Reader, zpoolPath string, handler func(string, zfsSysctl, uint64)) error {
scanner := bufio.NewScanner(reader)
parseLine := false
var fields []string
for scanner.Scan() {
line := strings.Fields(scanner.Text())
if !parseLine && len(line) >= 12 && line[0] == "nread" {
//Start parsing from here.
parseLine = true
fields = make([]string, len(line))
copy(fields, line)View on GitHub (pinned to 17ddd77c59)