neondatabase/neon · error
cgroups v2 not supported
Error message
cgroups v2 not supported
What it means
CgroupWatcher::new requires the unified cgroup v2 hierarchy; is_cgroup2_unified_mode() (from the cgroups-rs crate) checks whether /sys/fs/cgroup is mounted as cgroup2. On hybrid or pure cgroup v1 systems the vm_monitor refuses to start with this error.
Source
Thrown at libs/vm_monitor/src/cgroup.rs:62
/// The `CgroupWatcher` primarily achieves this by reading from a stream of
/// `MonitorEvent`s. See `main_signals_loop` for details on how to keep the
/// cgroup happy.
#[derive(Debug)]
pub struct CgroupWatcher {
pub config: Config,
/// The actual cgroup we are watching and managing.
cgroup: cgroups_rs::Cgroup,
}
impl CgroupWatcher {
/// Create a new `CgroupWatcher`.
#[tracing::instrument(skip_all, fields(%name))]
pub fn new(name: String) -> anyhow::Result<Self> {
// TODO: clarify exactly why we need v2
// Make sure cgroups v2 (aka unified) are supported
if !is_cgroup2_unified_mode() {
anyhow::bail!("cgroups v2 not supported");
}
let cgroup = cgroups_rs::Cgroup::load(hierarchies::auto(), &name);
Ok(Self {
cgroup,
config: Default::default(),
})
}
/// The entrypoint for the `CgroupWatcher`.
#[tracing::instrument(skip_all)]
pub async fn watch(
&self,
updates: watch::Sender<(Instant, MemoryHistory)>,
) -> anyhow::Result<()> {
// this requirement makes the code a bit easier to work with; see the config for more.
assert!(self.config.memory_history_len <= self.config.memory_history_log_interval);
View on GitHub (pinned to 8f60b04da4)
Solutions
- Boot with systemd.unified_cgroup_hierarchy=1 added to the kernel cmdline, then reboot
- Upgrade to a distro that defaults to cgroup v2 (modern Debian, Ubuntu, Fedora)
- For containers, ensure the host provides the unified hierarchy to the guest
Example fix
# /etc/default/grub # before GRUB_CMDLINE_LINUX="quiet" # after GRUB_CMDLINE_LINUX="quiet systemd.unified_cgroup_hierarchy=1" # then: update-grub && reboot
Defensive patterns
Strategy: validation
Validate before calling
fn cgroup2_available() -> bool {
use nix::sys::statfs;
statfs::statfs("/sys/fs/cgroup")
.map(|s| s.filesystem_type() == statfs::CGROUP2_SUPER_MAGIC)
.unwrap_or(false)
}
anyhow::ensure!(cgroup2_available(), "vm_monitor requires cgroup v2; boot with systemd.unified_cgroup_hierarchy=1"); Try / catch
if let Err(e) = CgroupWatcher::new(name.clone()) {
if e.to_string().contains("cgroups v2 not supported") {
// host misconfiguration: guide the operator to enable the unified hierarchy, do not retry
}
return Err(e);
} Prevention
- Bake a cgroup v2 check into host provisioning and container base images
- Monitor for hosts drifting back to hybrid mode after kernel changes
When it happens
Trigger: Starting vm_monitor on a host booted with cgroup v1 or hybrid mode: systemd.unified_cgroup_hierarchy=0 on the kernel cmdline, older distros (CentOS 7 era), or containers whose host only exposes v1.
Common situations: Legacy VMs or bare-metal hosts; custom kernels built without cgroup2; older container runtimes orchestrating on v1 hosts.
Related errors
- could not find memory subsystem
- resource_multiplier must be between 0.0 and 1.0 exclusive, g
- spread_factor must be >= 0, got {}
- incompatible resource_multipler and spread_factor
- file cache size query returned no rows
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/c89cf7055242fd5f.
Report an issue: GitHub.