cross-rs/cross · error

want driver overlay2, got

Error message

want driver overlay2, got {driver_name}

What it means

When parsing `docker info` output to locate user mounts, cross only supports containers backed by the overlay2 storage driver. `dockerinfo_parse_rootful_mount` (or nearby) builds a MountDetail only when the driver name is overlay2; otherwise it bails with the actual driver name it saw.

Solutions

  1. Check `docker info --format '{{.Driver}}'` and reconfigure the daemon to use overlay2 (set "storage-driver": "overlay2" in daemon.json).
  2. On rootless setups, switch to a rootless driver that reports overlay2/fuse-overlayfs or migrate storage.
  3. Upgrade the host/kernel so overlay2 is supported, then restart the daemon.

Example fix

// /etc/docker/daemon.json
// before
{ }
// after
{ "storage-driver": "overlay2" }
Defensive patterns

Strategy: validation

Validate before calling

const { execSync } = require('child_process');
function assertOverlay2() {
  const driver = execSync("docker info --format '{{.Driver}}'").toString().trim();
  if (driver !== 'overlay2') {
    throw new Error(`docker storage driver is ${driver}; overlay2 required`);
  }
}

Prevention

When it happens

Trigger: Running cross against a Docker daemon whose storage driver is not overlay2 (e.g. vfs, devicemapper, btrfs, zfs, fuse-overlayfs) while cross inspects root mounts from `docker info`.

Common situations: Rootless Docker or Podman setups using alternative snapshot/storage drivers; older kernels falling back to vfs; distros with devicemapper storage.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of cross-rs/cross@8c1a8aa4b6 (2026-09-13). Data as JSON: /api/errors/9f9777b538399cbf. Report an issue: GitHub.

Appendix: source

Thrown at src/docker/shared.rs:1427

fn dockerinfo_parse_root_mount_path(info: &serde_json::Value) -> Result<MountDetail> {
    let driver_name = info
        .pointer("/0/GraphDriver/Name")
        .and_then(|v| v.as_str())
        .ok_or_else(|| eyre::eyre!("no driver name found"))?;

    if driver_name.to_lowercase().contains("overlay") {
        let path = info
            .pointer("/0/GraphDriver/Data/MergedDir")
            .and_then(|v| v.as_str())
            .ok_or_else(|| eyre::eyre!("No merge directory found"))?;

        Ok(MountDetail {
            source: PathBuf::from(&path),
            destination: PathBuf::from("/"),
        })
    } else {
        eyre::bail!("want driver overlay2, got {driver_name}")
    }
}

fn dockerinfo_parse_user_mounts(info: &serde_json::Value) -> Vec<MountDetail> {
    info.pointer("/0/Mounts")
        .and_then(|v| v.as_array())
        .map_or_else(Vec::new, |v| {
            let make_path = |v: &serde_json::Value| {
                PathBuf::from(&v.as_str().expect("docker mount should be defined"))
            };
            let mut mounts = vec![];
            for details in v {
                let source = make_path(&details["Source"]);
                let destination = make_path(&details["Destination"]);
                mounts.push(MountDetail {
                    source,
                    destination,
                });

View on GitHub (pinned to 8c1a8aa4b6)