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

  1. Verify the zpool and dataset names in the file path actually exist in the file content
  2. Check the file is a full objset kstat dump including data lines, not just types
  3. Dump a fresh objset file from a live system (cat /proc/spl/kstat/zfs/<pool>/objset-*) and compare format
  4. 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

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


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)