prometheus/node_exporter · error
could not parse expected integer value for
Error message
could not parse expected integer value for %q: %w
What it means
parsePoolProcfsFile walks a /proc/spl/kstat/zfs/<pool> file whose first line is a header of column names. For each row it expects every value to parse as uint64; when strconv.ParseUint fails it wraps the parse error with the fully qualified kstat key (e.g. kstat.zfs.misc.zfetch_reclaim_success.hits) so the offending metric is identified. This means the fixture/proc file contained a non-numeric token where the header declared a numeric column.
Solutions
- Inspect the reported kstat key's column in the procfs file/fixture and fix the non-numeric value
- Verify the header line and data line have the same number of fields (no shift)
- Regenerate fixtures from a real system instead of hand-editing them
- Confirm the ZFS build emits uint64 values for that kstat
Example fix
// before
value, err := strconv.ParseUint(line[i], 10, 64)
// after
value, err := strconv.ParseUint(strings.TrimSpace(line[i]), 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected integer value for %q: %w", key, err)
} Defensive patterns
Strategy: validation
Validate before calling
for i, v := range line {
if _, err := strconv.ParseUint(strings.TrimSpace(v), 10, 64); err != nil {
// skip or fix fixture row i before calling handler
}
} Try / catch
if err := c.parsePoolProcfsFile(f, pool, handler); err != nil {
var numErr *strconv.NumError
if errors.As(err, &numErr) {
c.logger.Warn("skipping malformed kstat value", "err", err)
return nil
}
return err
} Prevention
- Validate fixture files against the kstat header before tests
- Use %w wrapping so the underlying NumError is preserved
- Regenerate fixtures with make update_fixtures from a real system
- Trim whitespace before parsing
When it happens
Trigger: updatePoolStats reads a zpool kstat procfs file and a field value on a data line is empty, contains a value like '-' or a float, or columns shifted so a non-numeric field aligns with a numeric header column.
Common situations: Corrupted or hand-edited /proc/spl/kstat/zfs fixtures in tests; running against a ZFS version that emits new non-numeric columns; misaligned columns after header/value mismatch in mock files.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- could not parse expected integer value for
- ZFS / ZFS statistics are not available
- failed to parse /proc/net/dev
- did not parse a single
- interrupts empty
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/0ba666d55627962f.
Report an issue: GitHub.
Appendix: source
Thrown at collector/zfs_linux.go:288
}
if !parseLine {
continue
}
zpoolPathElements := strings.Split(zpoolPath, "/")
pathLen := len(zpoolPathElements)
if pathLen < 2 {
return fmt.Errorf("zpool path did not return at least two elements")
}
zpoolName := zpoolPathElements[pathLen-2]
zpoolFile := zpoolPathElements[pathLen-1]
for i, field := range fields {
key := fmt.Sprintf("kstat.zfs.misc.%s.%s", zpoolFile, field)
value, err := strconv.ParseUint(line[i], 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected integer value for %q: %w", key, err)
}
handler(zpoolName, zfsSysctl(key), value)
}
}
return scanner.Err()
}
func (c *zfsCollector) parsePoolObjsetFile(reader io.Reader, zpoolPath string, handler func(string, string, zfsSysctl, uint64)) error {
scanner := bufio.NewScanner(reader)
parseLine := false
var zpoolName, datasetName string
for scanner.Scan() {
line := scanner.Text()
parts := strings.Fields(line)
if !parseLine && len(parts) == 3 && parts[0] == "name" && parts[1] == "type" && parts[2] == "data" {View on GitHub (pinned to 17ddd77c59)