jdx/mise · error · eyre::Report

legacy 'docker-compose' v1 is unsupported; install Docker Co

Error message

legacy 'docker-compose' v1 is unsupported; install Docker Compose v2 or set command to a compatible frontend

What it means

When no `command`/`engine_command` is configured, mise autodetects a compose frontend: a `docker` CLI with the compose plugin wins; otherwise a `docker-compose` binary is probed, and if it does not report Compose v2, mise bails. The legacy Python docker-compose v1 lacks the v2 CLI surface mise relies on (e.g. `--wait`, `config --hash=*`), so it is rejected outright rather than partially supported.

Source

Thrown at src/system/compose.rs:847

            return resolve_command(&self.command);
        }
        self.detected_compose_command()?
            .ok_or_else(|| eyre!("neither 'docker compose' nor 'docker-compose' was found"))
    }

    fn detected_compose_command(&self) -> Result<Option<Vec<String>>> {
        if let Some(docker) = crate::file::which("docker") {
            let docker = docker.to_string_lossy().to_string();
            if compose_plugin_available(&docker) {
                return Ok(Some(vec![docker, "compose".to_string()]));
            }
        }
        if let Some(compose) = crate::file::which("docker-compose") {
            let compose = compose.to_string_lossy().to_string();
            if standalone_compose_v2_available(&compose) {
                return Ok(Some(vec![compose]));
            }
            bail!(
                "legacy 'docker-compose' v1 is unsupported; install Docker Compose v2 or set command to a compatible frontend"
            );
        }
        Ok(None)
    }

    fn resolved_engine_command(&self) -> Result<Vec<String>> {
        if !self.engine_command.is_empty() {
            return resolve_command(&self.engine_command);
        }
        if let Some(command) = engine_command_from_compose_command(&self.command) {
            return resolve_command(command);
        }
        if let Some(docker) = crate::file::which("docker") {
            return Ok(vec![docker.to_string_lossy().to_string()]);
        }
        bail!("container engine command 'docker' was not found; set engine_command explicitly")
    }

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Install Docker Compose v2, ideally the docker CLI plugin (`apt install docker-compose-plugin` or equivalent), then re-run.
  2. Or point mise at a v2-compatible frontend explicitly in the project table: `command = ["docker", "compose"]` (or a standalone v2 path).
  3. Verify with `docker compose version` (want 'v2') and remove the legacy `docker-compose` from PATH to avoid ambiguity.

Example fix

# before (autodetect finds legacy docker-compose v1)
[bootstrap.compose.web]
project_dir = "/srv/web"

# after
[bootstrap.compose.web]
project_dir = "/srv/web"
command = ["docker", "compose"]
Defensive patterns

Strategy: fallback

Validate before calling

#!/usr/bin/env bash
# verify a v2 frontend exists before relying on autodetect
docker compose version 2>/dev/null | grep -q 'version v2' \
  || docker-compose version 2>/dev/null | grep -q 'v2' \
  || echo 'no compose v2 found: install docker-compose-plugin or set command'

Try / catch

match compose::plans(&requests) {
    Ok(plans) => { /* proceed */ }
    Err(err) if err.to_string().contains("legacy 'docker-compose' v1") => {
        // fallback: pin an explicit v2 frontend instead of autodetect
        // [bootstrap.compose.web] command = ["docker", "compose"]
        return Err(err);
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Host has no docker CLI (or a docker CLI without the compose plugin) and a `docker-compose` binary on PATH that is v1 (or otherwise fails the v2 probe `standalone_compose_v2_available`). Autodetection in `detected_compose_command` bails before any converge.

Common situations: Old hosts where `docker-compose` was installed via pip or the old distro package; minimal containers with the standalone v1 binary; PATH ordering that surfaces an ancient `docker-compose` before a v2 install.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/f4739dd9de0e39d7. Report an issue: GitHub.