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

  1. Boot with systemd.unified_cgroup_hierarchy=1 added to the kernel cmdline, then reboot
  2. Upgrade to a distro that defaults to cgroup v2 (modern Debian, Ubuntu, Fedora)
  3. 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

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


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/c89cf7055242fd5f. Report an issue: GitHub.