{"record":{"id":"f240df552c7a8ef3","repo":"jdx/mise","slug":"bootstrap-compose-project-name-wait-timeout-re","errorCode":null,"errorMessage":"bootstrap compose project '{name}' wait_timeout requires wait = true","messagePattern":"bootstrap compose project '(.+?)' wait_timeout requires wait = true","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/compose.rs","lineNumber":292,"sourceCode":"        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!(\n                \"bootstrap compose project '{name}' renew_anonymous_volumes requires state = \\\"running\\\"\"\n            );\n        }\n        let explicit_dependencies = config\n            .depends_on","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/compose.rs#L274-L310","documentation":"`wait_timeout` bounds how long mise waits for `docker compose up --wait` to report healthy; it only has meaning when waiting is enabled. `ComposeRequest::from_toml` rejects a timeout set while `wait` is false (its default) so the silently-ignored option cannot mislead you.","triggerScenarios":"A compose table sets `wait_timeout = 120` without `wait = true` on the same table. Parsing bails immediately during `mise bootstrap compose plan`/`apply`.","commonSituations":"Adding a timeout while debugging slow healthchecks but forgetting the wait flag; upgrading configs after the wait feature changed defaults.","solutions":["Add `wait = true` next to the timeout.","Or remove `wait_timeout` if you do not actually want mise to wait for health."],"exampleFix":"# before\n[bootstrap.compose.web]\nproject_dir = \"/srv/web\"\nwait_timeout = 120\n\n# after\n[bootstrap.compose.web]\nproject_dir = \"/srv/web\"\nwait = true\nwait_timeout = 120","handlingStrategy":"validation","validationCode":"if let Some(t) = cfg.wait_timeout {\n    assert!(cfg.wait, \"wait_timeout = {t} requires wait = true\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat wait_timeout as a sub-option of wait: always write the pair together.","Config-lint compose tables in CI so forgotten wait = true fails fast."],"tags":["mise","bootstrap","compose","config","wait","validation"],"backgroundTag":"conflicting-config-options","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}