prometheus/node_exporter · error

invalid line in meminfo

Error message

invalid line in meminfo: %s

What it means

This error is returned by parseMemInfoNuma in collector/meminfo_numa_linux.go:147 when a line from a per-NUMA-node meminfo file has a field count other than 4 fields (no unit) or 5 fields with 'kB' as the unit. The switch on len(parts) rejects any other shape, so unexpected units (e.g. 'MB', 'GB') or extra/missing columns cause a full parse failure.

Solutions

  1. Check the failing line in /sys/devices/system/node/node*/meminfo for unexpected unit or column count
  2. If the kernel emits a new unit (MB/GB), extend the switch to handle it and scale accordingly
  3. Confirm kernel version; update the collector parser if sysfs format changed upstream
  4. Rebuild with -tags nomeminfo_numa to skip this collector on unsupported platforms
  5. Report the format upstream via a GitHub issue with the exact offending line

Example fix

// before
case l == 5 && parts[4] == "kB": // has unit
	fv *= 1024
default:
	return nil, fmt.Errorf("invalid line in meminfo: %s", line)
// after
case l == 5 && parts[4] == "kB":
	fv *= 1024
case l == 5 && parts[4] == "MB":
	fv *= 1024 * 1024
default:
	return nil, fmt.Errorf("invalid line in meminfo: %s", line)
Defensive patterns

Strategy: validation

Validate before calling

// Validate line shape before parse: expect 4 fields or 5 with kB unit
parts := strings.Fields(line)
if !(len(parts) == 4 || (len(parts) == 5 && parts[4] == "kB")) {
	return fmt.Errorf("unsupported meminfo line shape: %q", line)
}

Try / catch

_, err := parseMemInfoNuma(f)
if err != nil {
	if strings.Contains(err.Error(), "invalid line in meminfo") {
		// fall back to non-NUMA meminfo collector or disable meminfo_numa
	}
	return err
}

Prevention

When it happens

Trigger: parseMemInfoNuma reads a line whose word count is not 4, or is 5 but the 5th word is not exactly 'kB' — e.g. 'Node 0 MemFree: 1024 MB' or a line with an unexpected trailing column.

Common situations: Kernels emitting units other than kB for per-node meminfo entries; custom kernels or hypervisors adding columns; parsing hand-edited or fixture files; future kernel changes introducing new units.

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/5bc67bf1592a2864. Report an issue: GitHub.

Appendix: source

Thrown at collector/meminfo_numa_linux.go:147

	)

	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()
}

func parseMemInfoNumaStat(r io.Reader, nodeNumber string) ([]meminfoMetric, error) {
	var (
		numaStat []meminfoMetric
		scanner  = bufio.NewScanner(r)
	)

	for scanner.Scan() {

View on GitHub (pinned to 17ddd77c59)