jdx/mise · error

bootstrap compose project '{name}' project_dir must be absol

Error message

bootstrap compose project '{name}' project_dir must be absolute: {}

What it means

`ComposeRequest::from_toml` requires `project_dir` to be absolute. The directory is the anchor for resolving `files` and `env_files` and becomes a directory resource dependency, and the privileged apply step needs an unambiguous location, so relative project directories are rejected at parse time with the offending path echoed.

Source

Thrown at src/system/compose.rs:275

    dry_run_actions
        .get(&request.name)
        .copied()
        .filter(|action| {
            matches!(
                action,
                ResourceAction::Create | ResourceAction::Update | ResourceAction::Remove
            )
        })
        .unwrap_or(action)
}

impl ComposeRequest {
    fn from_toml(name: String, config: ComposeTomlConfig) -> Result<Self> {
        if name.is_empty() {
            bail!("bootstrap compose project names cannot be empty");
        }
        if !config.project_dir.is_absolute() {
            bail!(
                "bootstrap compose project '{name}' project_dir must be absolute: {}",
                config.project_dir.display()
            );
        }
        validate_project_name(config.project_name.as_deref())?;
        validate_values("profile", &config.profiles)?;
        validate_values("service", &config.services)?;
        validate_values("oneshot service", &config.oneshot)?;
        validate_command("command", &config.command)?;
        validate_command("engine_command", &config.engine_command)?;
        if config.state == ComposeState::Absent && !config.services.is_empty() {
            bail!(
                "bootstrap compose project '{name}' services cannot be combined with state = \"absent\" because compose down removes the entire project"
            );
        }
        if !config.wait && config.wait_timeout.is_some() {
            bail!("bootstrap compose project '{name}' wait_timeout requires wait = true");
        }

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Spell the directory from the root: `project_dir = "/srv/myapp/docker"`.
  2. Do not use `~`, `./`, or bare relative names; expand them yourself (e.g. via a config template) if you need host-dependent roots.
  3. Re-run `mise bootstrap compose plan` to confirm parsing and see the resolved file dependencies.

Example fix

# before
[bootstrap.compose.web]
project_dir = "./docker"

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

Strategy: validation

Validate before calling

let dir = std::path::Path::new(&cfg.project_dir);
assert!(dir.is_absolute(), "project_dir must be absolute: {}", dir.display());

Prevention

When it happens

Trigger: A compose table sets `project_dir = "./docker"`, `project_dir = "stack"`, or `project_dir = "~/apps/web"` — none satisfy `Path::is_absolute()` (mise does not expand `~` or cwd-relative paths here).

Common situations: Porting a docker-compose invocation that was always run from the repo; assuming mise resolves paths relative to the mise.toml file (it does not for this field); using `~` because that reads naturally in dotfiles configs.

Related errors


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