prometheus/node_exporter · error

invalid value in meminfo

Error message

invalid value in meminfo: %w

What it means

This error is returned by parseMemInfoNuma in collector/meminfo_numa_linux.go:140 when strconv.ParseFloat fails to parse field index 3 of a line from a per-NUMA-node /sys/devices/system/node/nodeN/meminfo file. The collector expects each line to contain a numeric value at parts[3] (the byte count); any non-numeric token there aborts the whole NUMA meminfo parse. It wraps the underlying strconv error via %w.

Solutions

  1. Inspect the failing /sys/devices/system/node/node*/meminfo content and check which line has a non-numeric 4th field
  2. Verify kernel version; if the sysfs format changed, update the parser to match the new layout
  3. Check for truncated reads or corrupted sysfs (virtualization/container artifacts) and re-read the file
  4. Rebuild with -tags nomeminfo_numa to disable the meminfo_numa collector if the platform cannot be supported
  5. File an issue upstream with the offending line if a supported kernel produces this format

Example fix

// before
fv, err := strconv.ParseFloat(parts[3], 64)
if err != nil {
	return nil, fmt.Errorf("invalid value in meminfo: %w", err)
}
// after (skip unparseable lines instead of failing the whole node)
fv, err := strconv.ParseFloat(parts[3], 64)
if err != nil {
	return nil, fmt.Errorf("invalid value in meminfo: %w", err) // keep abort, but log line context
}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate a meminfo line before relying on parts[3]
parts := strings.Fields(line)
if len(parts) < 4 {
	return fmt.Errorf("line too short: %q", line)
}
if _, err := strconv.ParseFloat(parts[3], 64); err != nil {
	return fmt.Errorf("non-numeric value in %q: %v", line, err)
}

Try / catch

metrics, err := parseMemInfoNuma(f)
if err != nil {
	var perr *strconv.NumError
	if errors.As(err, &perr) {
		// handle malformed numeric field: log and skip node or fall back to non-NUMA meminfo
	}
	return err
}

Prevention

When it happens

Trigger: parseMemInfoNuma reads a line from a node's meminfo whose 4th whitespace-separated field (parts[3]) is not a valid base-10 float, e.g. 'Node 0 MemUsed: abc kB' or a truncated/garbled line missing fields so parts[3] is actually a unit or label.

Common situations: Running a nonstandard or patched kernel that formats node meminfo differently; reading a fixture/test file with malformed lines; virtualized or container environments exposing a synthesized sysfs with unexpected content; kernel version changes altering the per-node meminfo layout.

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


AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07). Data as JSON: /api/errors/707347e1702b0ab2. Report an issue: GitHub.

Appendix: source

Thrown at collector/meminfo_numa_linux.go:140

}

func parseMemInfoNuma(r io.Reader) ([]meminfoMetric, error) {
	var (
		memInfo []meminfoMetric
		scanner = bufio.NewScanner(r)
		re      = regexp.MustCompile(`\((.*)\)`)
	)

	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}
		parts := strings.Fields(line)

		fv, err := strconv.ParseFloat(parts[3], 64)
		if err != nil {
			return nil, fmt.Errorf("invalid value in meminfo: %w", err)
		}
		switch l := len(parts); {
		case l == 4: // no unit
		case l == 5 && parts[4] == "kB": // has unit
			fv *= 1024
		default:
			return nil, fmt.Errorf("invalid line in meminfo: %s", line)
		}
		metric := strings.TrimRight(parts[2], ":")

		// Active(anon) -> Active_anon
		metric = re.ReplaceAllString(metric, "_${1}")
		memInfo = append(memInfo, meminfoMetric{metric, prometheus.GaugeValue, parts[1], fv})
	}

	return memInfo, scanner.Err()
}

View on GitHub (pinned to 17ddd77c59)