jdx/mise · error

repos: command failed in {}

Error message

repos: command failed in {}

What it means

exec runs the command with each repo as working directory; a non-zero exit status — or a spawn failure such as program-not-found, which is warned as `command failed to start` and counted as failed — marks that repo failed. Without continue-on-error, exec bails on the first failure, naming that single repo and skipping all remaining repos.

Source

Thrown at src/system/repos.rs:260

            "$ (cd {} && {})",
            status.request,
            shell_words::join(command)
        );
        let result = Command::new(program)
            .args(args)
            .current_dir(&status.request.path)
            .status();
        let failed = match result {
            Ok(exit) => !exit.success(),
            Err(err) => {
                warn!("repos: {}: command failed to start: {err}", status.request);
                true
            }
        };
        if failed {
            failures.push(status.request.to_string());
            if !continue_on_error {
                bail!("repos: command failed in {}", status.request);
            }
        }
    }
    if !failures.is_empty() {
        bail!("repos: command failed in {}", failures.join(", "));
    }
    Ok(())
}

fn status_one(request: &RepoRequest) -> Result<RepoStatus> {
    if !request.path.exists() {
        return Ok(missing_status(request));
    }
    if !request.path.is_dir() {
        return Ok(conflict_status(
            request,
            "path exists and is not a directory".to_string(),
        ));

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Reproduce manually: `cd <named repo> && <command>` to see the real exit status and output
  2. Fix the command or the repo state that makes it fail
  3. Enable the continue-on-error flag to run all repos and get the aggregated failure list instead of stopping at the first

Example fix

# before: stops at first failing repo
$ mise bootstrap repos exec -- git pull   # bail: repos: command failed in ~/src/x

# after: run all, report all failures
$ mise bootstrap repos exec --continue-on-error -- git pull
Defensive patterns

Strategy: try-catch

Validate before calling

fn command_runs_in_dir(program: &str, args: &[String], dir: &Path) -> bool {
    std::process::Command::new(program)
        .args(args)
        .current_dir(dir)
        .status()
        .map(|s| s.success())
        .unwrap_or(false)
}
// smoke-test the command in one repo before running exec over all of them

Try / catch

match repos::exec(&requests, &command, dry_run, /* continue_on_error */ true) {
    Ok(()) => {}
    Err(report) => {
        let msg = format!("{report:#}");
        if let Some(list) = msg.strip_prefix("repos: command failed in ") {
            let failed_repos: Vec<&str> = list.split(", ").collect();
            // handle each failed repo; other repos already ran
        }
    }
}

Prevention

When it happens

Trigger: The command exits non-zero in one repo (failing test, `grep` with no match, broken build); the program name does not exist on PATH, producing the `command failed to start` warning followed by this bail.

Common situations: Running `git pull` or test suites across many checkouts where one repo is broken; commands whose exit-code semantics (`grep`, `diff`) surprise in a loop context; PATH differences between interactive shell and bootstrap environment.

Related errors


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