{"record":{"id":"0197947fdcf79573","repo":"jdx/mise","slug":"bootstrap-compose-project-name-down-volumes-an","errorCode":null,"errorMessage":"bootstrap compose project '{name}' down_volumes and down_images require state = \"absent\"","messagePattern":"bootstrap compose project '(.+?)' down_volumes and down_images require state = \"absent\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/compose.rs","lineNumber":300,"sourceCode":"        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!(\n                \"bootstrap compose project '{name}' renew_anonymous_volumes requires state = \\\"running\\\"\"\n            );\n        }\n        let explicit_dependencies = config\n            .depends_on\n            .iter()\n            .map(|dependency| parse_dependency(dependency))\n            .collect::<Result<Vec<_>>>()?;\n        let services = dedupe(config.services);\n        let oneshot: IndexSet<String> = dedupe(config.oneshot).into_iter().collect();\n        if !services.is_empty() && oneshot.iter().any(|service| !services.contains(service)) {\n            bail!(\n                \"bootstrap compose project '{name}' oneshot services must also appear in services\"","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/compose.rs#L282-L318","documentation":"`down_volumes` and `down_images` map to `docker compose down` flags (`-v` and `--rmi`), and `down` only runs when a project is being removed. `ComposeRequest::from_toml` therefore rejects these teardown options on a table whose `state` is not `\"absent\"`.","triggerScenarios":"A compose table with `state = \"running\"` (or any non-absent state) sets `down_volumes = true` and/or `down_images = \"all\"|\"local\"`.","commonSituations":"Copying a known-good teardown block and flipping only `state` back to running; intending 'prune volumes/images on every converge', which this config does not express.","solutions":["Remove `down_volumes`/`down_images` from running-state tables.","If you want cleanup on removal, put them on the `state = \"absent\"` definition of that project.","Re-run `mise bootstrap compose plan` to confirm the config parses."],"exampleFix":"# before\n[bootstrap.compose.web]\nproject_dir = \"/srv/web\"\nstate = \"running\"\ndown_volumes = true\n\n# after\n[bootstrap.compose.web]\nproject_dir = \"/srv/web\"\nstate = \"running\"","handlingStrategy":"validation","validationCode":"if cfg.state != ComposeState::Absent {\n    assert!(!cfg.down_volumes && cfg.down_images.is_none(),\n        \"down_volumes/down_images only valid with state = absent\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Think of down_volumes/down_images as `docker compose down` flags — they belong only on absent-state tables.","Review copied compose blocks for leftover teardown options when changing state."],"tags":["mise","bootstrap","compose","config","conflicting-options","docker-down"],"backgroundTag":"conflicting-config-options","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}