{"record":{"id":"4b3a816ebf2b58ea","repo":"prometheus/node_exporter","slug":"couldn-t-get-memory-w","errorCode":null,"errorMessage":"couldn't get memory: %w","messagePattern":"couldn't get memory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"collector/memory_bsd.go","lineNumber":151,"sourceCode":"\t\t\t},\n\t\t\t{\n\t\t\t\tname:        \"swap_out_bytes_total\",\n\t\t\t\tdescription: \"Bytes paged out to swap devices\",\n\t\t\t\tmib:         \"vm.stats.vm.v_swappgsout\",\n\t\t\t\tvalueType:   prometheus.CounterValue,\n\t\t\t\tconversion:  fromPage,\n\t\t\t},\n\t\t},\n\t}, nil\n}\n\n// Update checks relevant sysctls for current memory usage, and kvm for swap\n// usage.\nfunc (c *memoryCollector) Update(ch chan<- prometheus.Metric) error {\n\tfor _, m := range c.sysctls {\n\t\tv, err := m.Value()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"couldn't get memory: %w\", err)\n\t\t}\n\n\t\t// Most are gauges.\n\t\tif m.valueType == 0 {\n\t\t\tm.valueType = prometheus.GaugeValue\n\t\t}\n\n\t\tch <- prometheus.MustNewConstMetric(\n\t\t\tprometheus.NewDesc(\n\t\t\t\tprometheus.BuildFQName(namespace, memorySubsystem, m.name),\n\t\t\t\tm.description,\n\t\t\t\tnil, nil,\n\t\t\t), m.valueType, v)\n\t}\n\n\tswapUsed, err := c.kvm.SwapUsedPages()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"couldn't get kvm: %w\", err)","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/prometheus/node_exporter/blob/17ddd77c59ba27e1508e9f7894b1e55b44d6aed3/collector/memory_bsd.go#L133-L169","documentation":"memoryCollector.Update iterates the configured sysctl metrics and calls m.Value() for each; if any sysctl read fails, the whole scrape aborts with this wrapped error. node_exporter throws it because one of the vm.stats.* sysctls backing the memory metrics could not be read during a collection cycle.","triggerScenarios":"A Prometheus scrape of the memory collector on FreeBSD/DragonFly when any sysctl in c.sysctls (e.g. vm.stats.vm.v_free_count) returns an error — missing MIB, permission denial, or transient kernel error.","commonSituations":"Jails with restricted sysctl visibility; kernel upgrades changing/renaming vm.stats MIBs; running the exporter as an unprivileged user without sysctl read access.","solutions":["Check which sysctl fails by running the MIBs manually with `sysctl <name>` as the exporter's user","Grant the exporter user read access or run with appropriate privileges","If in a jail, enable the needed sysctl visibility for the jail","Update node_exporter/kernel so the MIB set matches"],"exampleFix":"// before: one failing sysctl fails the whole scrape\nv, err := m.Value()\nif err != nil {\n\treturn fmt.Errorf(\"couldn't get memory: %w\", err)\n}\n// after (caller-side mitigation in a wrapper/scrape config)\nif _, err := unix.SysctlUint32(\"vm.stats.vm.v_free_count\"); err != nil {\n\t// fix access first: run `sysctl vm.stats.vm.v_free_count` as exporter user\n\tlogger.Warn(\"memory sysctl unavailable; memory metrics will be missing\")\n}","handlingStrategy":"retry","validationCode":"for mib in vm.stats.vm.v_page_size vm.stats.vm.v_free_count vm.stats.vm.v_inactive_count; do\n  sysctl -n \"$mib\" >/dev/null || echo \"missing: $mib\"\ndone","typeGuard":null,"tryCatchPattern":"if err := c.Update(ch); err != nil {\n\tif strings.Contains(err.Error(), \"couldn't get memory\") {\n\t\t// transient sysctl failure: retry the scrape once\n\t\truntime.Gosched()\n\t\treturn c.Update(ch)\n\t}\n\treturn err\n}","preventionTips":["Grant the exporter user sysctl read access","Alert on 'couldn't get memory' scrape errors to catch MIB drift after kernel upgrades","Test scrapes in staging after every kernel upgrade"],"tags":["freebsd","sysctl","memory","scrape"],"backgroundTag":"sysctl-call-failed","analyzedSha":"17ddd77c59ba27e1508e9f7894b1e55b44d6aed3","analyzedAt":"2026-09-07T17:54:06.211Z","contentChangedAt":"2026-09-07T17:54:06.211Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}