jdx/mise · error

bootstrap compose project

Error message

bootstrap compose project '{name}' wait_timeout requires wait = true

What it means

This error is thrown during TOML validation of a bootstrap compose project when `wait_timeout` is set but `wait = true` is not. The timeout only makes sense when mise is asked to wait for services to become healthy during `compose up`; without `wait`, the timeout would be silently ignored, so the library rejects the config instead. It is a fail-fast config consistency check.

Solutions

  1. Add `wait = true` to the compose project block
  2. Remove the `wait_timeout` key if you do not want to wait for service health

Example fix

# before
[system.compose.myproj]
services = ["db"]
wait_timeout = 30
# after
[system.compose.myproj]
services = ["db"]
wait = true
wait_timeout = 30
Defensive patterns

Strategy: validation

Validate before calling

// validate before committing config
if let Some(t) = cfg.wait_timeout {
    assert!(cfg.wait, "wait_timeout requires wait = true");
    assert!(t > 0, "wait_timeout must be > 0");
}

Prevention

When it happens

Trigger: Defining a `[system.compose.<name>]` bootstrap entry with `wait_timeout = <n>` while omitting `wait = true` (or leaving it at its default of false). Raised from `from_toml_with_origin` at parse time.

Common situations: Users copy an example that sets a healthcheck wait timeout but omit the `wait` flag; toggling `wait` off while leaving the timeout in place after previously enabling it.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/f240df552c7a8ef3. Report an issue: GitHub.

Appendix: source

Thrown at src/system/compose.rs:335

        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");
        }
        if config.wait_timeout == Some(0) {
            bail!("bootstrap compose project '{name}' wait_timeout must be greater than zero");
        }
        if config.state != ComposeState::Absent
            && (config.down_volumes || config.down_images.is_some())
        {
            bail!(
                "bootstrap compose project '{name}' down_volumes and down_images require state = \"absent\""
            );
        }
        if config.state != ComposeState::Running && config.renew_anonymous_volumes {
            bail!(
                "bootstrap compose project '{name}' renew_anonymous_volumes requires state = \"running\""
            );
        }
        let explicit_dependencies = config
            .depends_on

View on GitHub (pinned to 533346cc37)