prometheus/node_exporter · error
did not parse a single
Error message
did not parse a single %s %s metric
What it means
parsePoolObjsetFile requires that at least one uint64 metric line was successfully parsed for the given pool/dataset; if parseLine is still false after scanning the whole file it reports that no metric matched 'did not parse a single <pool> <dataset> metric'. This guards against silently exporting zero metrics from an empty or wrong-format file.
Solutions
- Verify the zpool and dataset names in the file path actually exist in the file content
- Check the file is a full objset kstat dump including data lines, not just types
- Dump a fresh objset file from a live system (cat /proc/spl/kstat/zfs/<pool>/objset-*) and compare format
- Update collector or ZFS if the kstat format changed
Example fix
// before
err := c.parsePoolObjsetFile(f, "badpool", "ds", handler)
// after
if _, err := os.Stat("/proc/spl/kstat/zfs/badpool/ds"); err != nil {
return // dataset does not exist; skip before parsing
} Defensive patterns
Strategy: validation
Validate before calling
data, _ := os.ReadFile("/proc/spl/kstat/zfs/tank/objset-0x2a")
if len(bytes.TrimSpace(data)) == 0 {
// file empty: skip before calling parsePoolObjsetFile
} Try / catch
if err := c.parsePoolObjsetFile(f, pool, ds, handler); err != nil {
if strings.HasPrefix(err.Error(), "did not parse a single") {
c.logger.Warn("no objset metrics parsed", "pool", pool, "dataset", ds)
return nil
}
return err
} Prevention
- Confirm the pool/dataset path exists on the host before collecting
- Compare against a live 'cat /proc/spl/kstat/zfs/<pool>/objset-*' dump
- Watch for ZFS version changes in kstat layout
- Log the parsed-file path with the error for debugging
When it happens
Trigger: The objset file contains no lines in 'key: uint64: value' form, only type declarations without data lines, or the file is empty — i.e. the dataset name in the path/file does not match any parsed content.
Common situations: Pointing the collector at a nonexistent dataset; ZFS upgrade changing objset kstat layout; fixtures containing only a header/type section; typo'd zpool or dataset name.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- could not parse expected integer value for
- could not parse expected integer value for
- ZFS / ZFS statistics are not available
- invalid value in meminfo
- invalid line in meminfo
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/87ef0dbaf7b78147.
Report an issue: GitHub.
Appendix: source
Thrown at collector/zfs_linux.go:332
if parts[0] == "dataset_name" {
zpoolPathElements := strings.Split(zpoolPath, "/")
pathLen := len(zpoolPathElements)
zpoolName = zpoolPathElements[pathLen-2]
datasetName = line[strings.Index(line, parts[2]):]
continue
}
if parts[1] == kstatDataUint64 {
key := fmt.Sprintf("kstat.zfs.misc.objset.%s", parts[0])
value, err := strconv.ParseUint(parts[2], 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected integer value for %q", key)
}
handler(zpoolName, datasetName, zfsSysctl(key), value)
}
}
if !parseLine {
return fmt.Errorf("did not parse a single %s %s metric", zpoolName, datasetName)
}
return scanner.Err()
}
func (c *zfsCollector) parsePoolStateFile(reader io.Reader, zpoolPath string, handler func(string, string, uint64)) error {
scanner := bufio.NewScanner(reader)
scanner.Scan()
actualStateName, err := scanner.Text(), scanner.Err()
if err != nil {
return err
}
actualStateName = strings.ToLower(actualStateName)
zpoolPathElements := strings.Split(zpoolPath, "/")
pathLen := len(zpoolPathElements)View on GitHub (pinned to 17ddd77c59)