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

  1. Check the kstat file content directly, e.g. `cat /proc/spl/kstat/zfs/arcstats`, confirming the `name type data` header and data rows exist.
  2. Verify the ZFS module is fully loaded (not mid-load) and the file is populated.
  3. 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)