prometheus/node_exporter · error

sysctl CTL_VM VM_UVMEXP failed

Error message

sysctl CTL_VM VM_UVMEXP failed: %w

What it means

This error is returned by getMemInfo in collector/meminfo_openbsd.go:72 when the CGO helper C.sysctl_uvmexp fails to fetch the VM_UVMEXP sysctl (CTL_VM / VM_UVMEXP) on OpenBSD. Without uvm.exp stats the meminfo collector cannot produce memory metrics, so the collection errors out. The underlying errno is wrapped via %w.

Solutions

  1. Check the OpenBSD kernel version supports CTL_VM/VM_UVMEXP (sysctl vm.uvmexp works in shell)
  2. Run node_exporter without restrictive pledge/sandbox settings that block sysctl(2)
  3. Rebuild node_exporter on/for the exact OpenBSD release so the C shim's sysctl mib matches
  4. Disable the meminfo collector (-collector.meminfo or build tags) if the platform can't provide uvmexp
  5. Verify with `sysctl -n vm.uvmexp` that the sysctl is readable by the exporter's user

Example fix

// before
if _, err := C.sysctl_uvmexp(&uvmexp); err != nil {
	return nil, fmt.Errorf("sysctl CTL_VM VM_UVMEXP failed: %w", err)
}
// after (skip sysctl-dependent metrics instead of failing collection)
if _, err := C.sysctl_uvmexp(&uvmexp); err != nil {
	return map[string]float64{}, fmt.Errorf("sysctl CTL_VM VM_UVMEXP failed: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Check sysctl availability before relying on meminfo metrics
// $ sysctl -n vm.uvmexp || echo "VM_UVMEXP unavailable"

Try / catch

metrics, err := c.getMemInfo()
if err != nil {
	if strings.Contains(err.Error(), "VM_UVMEXP failed") {
		// log warning, expose no meminfo metrics rather than failing the scrape
		return nil
	}
	return err
}

Prevention

When it happens

Trigger: getMemInfo calls C.sysctl_uvmexp(&uvmexp) and the sysctl call returns non-zero — e.g. running on an OpenBSD version where VM_UVMEXP is unavailable, a restricted environment (pledge/unveil or sandbox) blocking sysctl, or a syscall failure in the C shim.

Common situations: Running node_exporter on an OpenBSD release whose kernel removed or renumbered VM_UVMEXP; running under strict pledge() restrictions; compiled binaries mismatched with the running kernel; chroot environments missing sysctl access.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at collector/meminfo_openbsd.go:72

import "C"

type meminfoCollector struct {
	logger *slog.Logger
}

// NewMeminfoCollector returns a new Collector exposing memory stats.
func NewMeminfoCollector(logger *slog.Logger) (Collector, error) {
	return &meminfoCollector{
		logger: logger,
	}, nil
}

func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
	var uvmexp C.struct_uvmexp
	var bcstats C.struct_bcachestats

	if _, err := C.sysctl_uvmexp(&uvmexp); err != nil {
		return nil, fmt.Errorf("sysctl CTL_VM VM_UVMEXP failed: %w", err)
	}

	if _, err := C.sysctl_bcstats(&bcstats); err != nil {
		return nil, fmt.Errorf("sysctl CTL_VFS VFS_GENERIC VFS_BCACHESTAT failed: %w", err)
	}

	ps := float64(uvmexp.pagesize)

	// see uvm(9)
	return map[string]float64{
		"active_bytes":                  ps * float64(uvmexp.active),
		"cache_bytes":                   ps * float64(bcstats.numbufpages),
		"free_bytes":                    ps * float64(uvmexp.free),
		"inactive_bytes":                ps * float64(uvmexp.inactive),
		"size_bytes":                    ps * float64(uvmexp.npages),
		"swap_size_bytes":               ps * float64(uvmexp.swpages),
		"swap_used_bytes":               ps * float64(uvmexp.swpginuse),
		"swapped_in_pages_bytes_total":  ps * float64(uvmexp.pgswapin),

View on GitHub (pinned to 17ddd77c59)