{"record":{"id":"751069b6958e9943","repo":"jdx/mise","slug":"bootstrap-compose-project-name-services-cannot","errorCode":null,"errorMessage":"bootstrap compose project '{name}' services cannot be combined with state = \"absent\" because compose down removes the entire project","messagePattern":"bootstrap compose project '(.+?)' services cannot be combined with state = \"absent\" because compose down removes the entire project","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/compose.rs","lineNumber":330,"sourceCode":"        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        }\n        if config.wait_timeout == Some(0) {\n            bail!(\"bootstrap compose project '{name}' wait_timeout must be greater than zero\");\n        }\n        if config.state != ComposeState::Absent\n            && (config.down_volumes || config.down_images.is_some())\n        {\n            bail!(\n                \"bootstrap compose project '{name}' down_volumes and down_images require state = \\\"absent\\\"\"\n            );\n        }\n        if config.state != ComposeState::Running && config.renew_anonymous_volumes {\n            bail!(","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/compose.rs#L312-L348","documentation":"A declaration with state = \"absent\" removes the entire compose project (compose down), so per-service targeting is meaningless and dangerous. from_toml_with_origin rejects any absent-state declaration that also lists services, forcing users to express removal at project level.","triggerScenarios":"Config sets state = \"absent\" together with a non-empty services array under [bootstrap.compose.<name>]; a user edits a previously 'present' per-service declaration to state = \"absent\" to tear down one service.","commonSituations":"Trying to remove a single service by flipping state to absent; leftover services list in a teardown section; copy-paste of a present-state block with only state changed.","solutions":["Remove the services list from the absent-state declaration","If you only want some services gone, set state = \"present\" with the remaining services subset, or scale/remove services via the compose file itself","Use separate declarations: one present declaration for kept services, and plan full removal only when tearing down the whole project"],"exampleFix":"# before\n[bootstrap.compose.app]\nstate = \"absent\"\nservices = [\"web\", \"worker\"]\n\n# after\n[bootstrap.compose.app]\nstate = \"absent\"","handlingStrategy":"validation","validationCode":"def validate_absent_no_services(config: dict) -> None:\n    for name, decl in config.get(\"bootstrap\", {}).get(\"compose\", {}).items():\n        if decl.get(\"state\") == \"absent\" and decl.get(\"services\"):\n            raise ValueError(f\"{name}: services cannot be combined with state=absent\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat state = \"absent\" as a whole-project teardown","Remove individual services by editing the compose file or the present declaration, not by flipping state","Review diffs of bootstrap compose sections before merging"],"tags":["config","compose","validation"],"backgroundTag":"mutually-exclusive-options","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"}