{"record":{"id":"4ef0d1771990cd08","repo":"jdx/mise","slug":"bootstrap-compose-project-names-cannot-be-empty","errorCode":null,"errorMessage":"bootstrap compose project names cannot be empty","messagePattern":"bootstrap compose project names cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/compose.rs","lineNumber":272,"sourceCode":"    if !dry_run {\n        return action;\n    }\n    dry_run_actions\n        .get(&request.name)\n        .copied()\n        .filter(|action| {\n            matches!(\n                action,\n                ResourceAction::Create | ResourceAction::Update | ResourceAction::Remove\n            )\n        })\n        .unwrap_or(action)\n}\n\nimpl ComposeRequest {\n    fn from_toml(name: String, config: ComposeTomlConfig) -> 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        }","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/compose.rs#L254-L290","documentation":"`ComposeRequest::from_toml` builds each project from its `[bootstrap.compose.<name>]` table key; the key doubles as the project identifier, so an empty string is rejected immediately. TOML bare keys cannot be empty, so this only happens with an explicitly quoted empty key or programmatic construction.","triggerScenarios":"A config contains `[bootstrap.compose.\"\"]` (quoted empty table key), or tooling/templates generate a compose table with an unset project-name variable that interpolates to an empty string.","commonSituations":"Templated mise.toml (`[bootstrap.compose.\"{{ env.WEB_PROJECT }}\"]`) where the variable is empty on some hosts; hand-editing that accidentally produced an empty quoted key.","solutions":["Give the project a real name: `[bootstrap.compose.web]`.","If the name comes from a template variable, ensure it is non-empty before rendering (or skip the table entirely when unset).","Re-run `mise bootstrap compose plan` to confirm the config parses."],"exampleFix":"# before\n[bootstrap.compose.\"\"]\nproject_dir = \"/srv/web\"\n\n# after\n[bootstrap.compose.web]\nproject_dir = \"/srv/web\"","handlingStrategy":"validation","validationCode":"// before building requests from templated config, assert non-empty table keys\nassert!(!name.is_empty(), \"bootstrap compose project name must be non-empty\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When templating mise.toml, skip the whole compose table if the project-name variable is empty.","Prefer bare TOML keys ([bootstrap.compose.web]) so an empty name cannot even be written."],"tags":["mise","bootstrap","compose","config","validation"],"backgroundTag":"config-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}