jdx/mise · error
bootstrap compose project
Error message
bootstrap compose project '{name}' project_dir must be absolute: {} What it means
A bootstrap compose declaration's project_dir must be an absolute filesystem path because mise resolves and compares compose project locations globally. Relative paths are ambiguous (depends on cwd at apply time), so from_toml_with_origin rejects them and echoes the offending path.
Solutions
- Change project_dir to an absolute path (start with / on Unix, drive letter on Windows)
- If using a variable, ensure it expands to an absolute path or anchor it, e.g. "{{ env.HOME }}/srv/app" or an absolute ${HOME}/...
- Verify with `mise bootstrap plan` that the path resolves as intended
Example fix
# before [bootstrap.compose.app] project_dir = "./app" # after [bootstrap.compose.app] project_dir = "/home/me/src/app"
Defensive patterns
Strategy: validation
Validate before calling
import os
def validate_project_dir(config: dict) -> None:
for name, decl in config.get("bootstrap", {}).get("compose", {}).items():
d = decl.get("project_dir", "")
if not os.path.isabs(os.path.expandvars(d)):
raise ValueError(f"{name}: project_dir must be absolute: {d}") Prevention
- Always write absolute paths for project_dir
- If interpolating env vars, assert they expand to absolute paths
- Test configs with `mise bootstrap plan` on a fresh checkout
When it happens
Trigger: Config sets project_dir = "./compose" or "app/compose" under [bootstrap.compose.<name>]; a variable used in project_dir expands to a relative or empty path; programmatic construction passes a relative PathBuf.
Common situations: Hand-written configs using shorthand relative paths; env-var interpolation like project_dir = "${WORK_DIR}/app" where WORK_DIR is unset or relative; configs copied between machines with different layouts.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- agent ' ' `queue_directories` entry ' ' must be an absolute…
- an implied source entry key must be relative
- bootstrap compose project
- bootstrap compose project names cannot be empty
- brew-cask: app target
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/58ee0d9237268398.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/compose.rs:318
.unwrap_or(action)
}
impl ComposeRequest {
#[cfg(test)]
fn from_toml(name: String, config: ComposeTomlConfig) -> Result<Self> {
Self::from_toml_with_origin(name, config, None)
}
fn from_toml_with_origin(
name: String,
config: ComposeTomlConfig,
origin: Option<ResourceOrigin>,
) -> 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 533346cc37)