jdx/mise · error · eyre::Report

compose command failed with {status}

Error message

compose command failed with {status}

What it means

`run_command` executes the resolved compose command line (detected or configured `command`, optionally under sudo via `crate::system::sudo::run`) with `compose_env()` applied, logging `$ program args` at info level. A non-zero exit from docker/compose bails with the exit status; the child's stderr — printed to the terminal — is the actual reason (port conflict, build failure, pull auth, daemon down).

Source

Thrown at src/system/compose.rs:641

        args.extend(self.action_args());
        let mut commands = vec![(program, args)];
        if let Some(command) = orphan_removal {
            commands.push(command);
        }
        commands
    }

    fn run_command(&self, program: &str, args: &[String]) -> Result<()> {
        if self.sudo {
            crate::system::sudo::run(program, args, &compose_env())
        } else {
            info!("$ {} {}", program, shell_words::join(args));
            let status = Command::new(program)
                .args(args)
                .envs(compose_env())
                .status()?;
            if !status.success() {
                bail!("compose command failed with {status}");
            }
            Ok(())
        }
    }

    fn stopped_orphan_removal_command(&self) -> Result<Option<(String, Vec<String>)>> {
        let Some(args) = self.stopped_orphan_removal_args() else {
            return Ok(None);
        };
        let command = self.resolved_engine_command()?;
        command_with_args(command, args).map(Some)
    }

    fn dry_run_stopped_orphan_removal_command(&self) -> Result<Option<(String, Vec<String>)>> {
        let Some(args) = self.stopped_orphan_removal_args() else {
            return Ok(None);
        };
        command_with_args(self.configured_engine_command(), args).map(Some)

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Read the stderr above the error — it names the real cause; the mise line just above (`$ docker compose ...`) is the exact command to reproduce.
  2. Run that logged command manually in `project_dir` with the same files/env-files to iterate on the fix.
  3. Fix the environment (free the port, fix registry auth for the sudo context, start the engine, upgrade compose) and re-run `mise bootstrap compose apply`.
Defensive patterns

Strategy: try-catch

Validate before calling

#!/usr/bin/env bash
# preflight the exact converge command before letting mise run it
cd /srv/web && docker compose -f compose.yml config --quiet || exit 1
docker compose version | grep -q 'v2' || { echo 'compose v2 required' >&2; exit 1; }

Try / catch

match compose::apply_with_dry_run_actions(&reqs, &actions, dry_run, yes) {
    Ok(()) => {}
    Err(err) if err.to_string().contains("compose command failed") => {
        // terminal: status only. The child's stderr above names the cause;
        // reproduce with the logged `$ docker compose ...` line, fix env (port/auth/build), rerun.
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: `docker compose up`/`down`/`pull` failing for any environmental reason: 'port is already allocated', image pull denied, Dockerfile build error, engine socket permission failure under sudo, or compose v2 CLI syntax unsupported by the installed version.

Common situations: Competing containers holding ports; registry credentials available to the user but not under `sudo = true`; compose file using features newer than the installed compose; daemon not running.

Related errors


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