{"record":{"id":"58ee0d9237268398","repo":"jdx/mise","slug":"bootstrap-compose-project-name-project-dir-mus","errorCode":null,"errorMessage":"bootstrap compose project '{name}' project_dir must be absolute: {}","messagePattern":"bootstrap compose project '(.+?)' project_dir must be absolute: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/compose.rs","lineNumber":318,"sourceCode":"        .unwrap_or(action)\n}\n\nimpl ComposeRequest {\n    #[cfg(test)]\n    fn from_toml(name: String, config: ComposeTomlConfig) -> Result<Self> {\n        Self::from_toml_with_origin(name, config, None)\n    }\n\n    fn from_toml_with_origin(\n        name: String,\n        config: ComposeTomlConfig,\n        origin: Option<ResourceOrigin>,\n    ) -> Result<Self> {\n        if name.is_empty() {\n            bail!(\"bootstrap compose project names cannot be empty\");\n        }\n        if !config.project_dir.is_absolute() {\n            bail!(\n                \"bootstrap compose project '{name}' project_dir must be absolute: {}\",\n                config.project_dir.display()\n            );\n        }\n        validate_project_name(config.project_name.as_deref())?;\n        validate_values(\"profile\", &config.profiles)?;\n        validate_values(\"service\", &config.services)?;\n        validate_values(\"oneshot service\", &config.oneshot)?;\n        validate_command(\"command\", &config.command)?;\n        validate_command(\"engine_command\", &config.engine_command)?;\n        if config.state == ComposeState::Absent && !config.services.is_empty() {\n            bail!(\n                \"bootstrap compose project '{name}' services cannot be combined with state = \\\"absent\\\" because compose down removes the entire project\"\n            );\n        }\n        if !config.wait && config.wait_timeout.is_some() {\n            bail!(\"bootstrap compose project '{name}' wait_timeout requires wait = true\");\n        }","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/compose.rs#L300-L336","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\n[bootstrap.compose.app]\nproject_dir = \"./app\"\n\n# after\n[bootstrap.compose.app]\nproject_dir = \"/home/me/src/app\"","handlingStrategy":"validation","validationCode":"import os\ndef validate_project_dir(config: dict) -> None:\n    for name, decl in config.get(\"bootstrap\", {}).get(\"compose\", {}).items():\n        d = decl.get(\"project_dir\", \"\")\n        if not os.path.isabs(os.path.expandvars(d)):\n            raise ValueError(f\"{name}: project_dir must be absolute: {d}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["config","compose","path-validation"],"backgroundTag":"invalid-config-value","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}