{"record":{"id":"c89cf7055242fd5f","repo":"neondatabase/neon","slug":"cgroups-v2-not-supported","errorCode":null,"errorMessage":"cgroups v2 not supported","messagePattern":"cgroups v2 not supported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/vm_monitor/src/cgroup.rs","lineNumber":62,"sourceCode":"/// The `CgroupWatcher` primarily achieves this by reading from a stream of\n/// `MonitorEvent`s. See `main_signals_loop` for details on how to keep the\n/// cgroup happy.\n#[derive(Debug)]\npub struct CgroupWatcher {\n    pub config: Config,\n\n    /// The actual cgroup we are watching and managing.\n    cgroup: cgroups_rs::Cgroup,\n}\n\nimpl CgroupWatcher {\n    /// Create a new `CgroupWatcher`.\n    #[tracing::instrument(skip_all, fields(%name))]\n    pub fn new(name: String) -> anyhow::Result<Self> {\n        // TODO: clarify exactly why we need v2\n        // Make sure cgroups v2 (aka unified) are supported\n        if !is_cgroup2_unified_mode() {\n            anyhow::bail!(\"cgroups v2 not supported\");\n        }\n        let cgroup = cgroups_rs::Cgroup::load(hierarchies::auto(), &name);\n\n        Ok(Self {\n            cgroup,\n            config: Default::default(),\n        })\n    }\n\n    /// The entrypoint for the `CgroupWatcher`.\n    #[tracing::instrument(skip_all)]\n    pub async fn watch(\n        &self,\n        updates: watch::Sender<(Instant, MemoryHistory)>,\n    ) -> anyhow::Result<()> {\n        // this requirement makes the code a bit easier to work with; see the config for more.\n        assert!(self.config.memory_history_len <= self.config.memory_history_log_interval);\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/libs/vm_monitor/src/cgroup.rs#L44-L80","documentation":"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.","triggerScenarios":"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.","commonSituations":"Legacy VMs or bare-metal hosts; custom kernels built without cgroup2; older container runtimes orchestrating on v1 hosts.","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"],"exampleFix":"# /etc/default/grub\n# before\nGRUB_CMDLINE_LINUX=\"quiet\"\n# after\nGRUB_CMDLINE_LINUX=\"quiet systemd.unified_cgroup_hierarchy=1\"\n# then: update-grub && reboot","handlingStrategy":"validation","validationCode":"fn cgroup2_available() -> bool {\n    use nix::sys::statfs;\n    statfs::statfs(\"/sys/fs/cgroup\")\n        .map(|s| s.filesystem_type() == statfs::CGROUP2_SUPER_MAGIC)\n        .unwrap_or(false)\n}\n\nanyhow::ensure!(cgroup2_available(), \"vm_monitor requires cgroup v2; boot with systemd.unified_cgroup_hierarchy=1\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = CgroupWatcher::new(name.clone()) {\n    if e.to_string().contains(\"cgroups v2 not supported\") {\n        // host misconfiguration: guide the operator to enable the unified hierarchy, do not retry\n    }\n    return Err(e);\n}","preventionTips":["Bake a cgroup v2 check into host provisioning and container base images","Monitor for hosts drifting back to hybrid mode after kernel changes"],"tags":["linux","cgroups","rust","vm-monitor","system-configuration"],"backgroundTag":"cgroup-v2-unavailable","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}