{"record":{"id":"4971e8a37f460aa2","repo":"zeroclaw-labs/zeroclaw","slug":"cloud-ops-iac-tools-must-not-be-empty-when-cloud-o","errorCode":null,"errorMessage":"cloud_ops.iac_tools must not be empty when cloud_ops is enabled","messagePattern":"cloud_ops\\.iac_tools must not be empty when cloud_ops is enabled","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":18600,"sourceCode":"                        \"cloud_ops.supported_clouds[{i}] must not be empty\"\n                    );\n                }\n            }\n            if !self.supported_clouds.contains(&self.default_cloud) {\n                anyhow::bail!(\n                    \"cloud_ops.default_cloud '{}' is not in cloud_ops.supported_clouds {:?}\",\n                    self.default_cloud,\n                    self.supported_clouds\n                );\n            }\n            if self.cost_threshold_monthly_usd < 0.0 {\n                anyhow::bail!(\n                    \"cloud_ops.cost_threshold_monthly_usd must be non-negative, got {}\",\n                    self.cost_threshold_monthly_usd\n                );\n            }\n            if self.iac_tools.is_empty() {\n                anyhow::bail!(\"cloud_ops.iac_tools must not be empty when cloud_ops is enabled\");\n            }\n        }\n        Ok(())\n    }\n}\n\nfn default_cloud_ops_cloud() -> String {\n    \"aws\".into()\n}\n\nfn default_cloud_ops_supported_clouds() -> Vec<String> {\n    vec![\"aws\".into(), \"azure\".into(), \"gcp\".into()]\n}\n\nfn default_cloud_ops_iac_tools() -> Vec<String> {\n    vec![\"terraform\".into()]\n}\n","sourceCodeStart":18582,"sourceCodeEnd":18618,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L18582-L18618","documentation":"ZeroClaw rejects a config in which the [cloud_ops] section is enabled but declares no infrastructure-as-code tools. The check runs at the end of CloudOpsConfig::validate() (after default_cloud, supported_clouds, and cost-threshold guards) because an enabled cloud_ops deployment is expected to manage at least one IaC tool such as terraform or pulumi. Fresh configs inherit a non-empty default list (default_cloud_ops_iac_tools()), so hitting this almost always means an explicit `iac_tools = []` or a config layer that cleared the list.","triggerScenarios":"Set `[cloud_ops] enabled = true` together with `iac_tools = []`, or apply an overlay/profile/env-mirror layer that replaces the default list with an empty array. Config::validate() aborts with this message before the application starts.","commonSituations":"Trimming a copied example config down to the bone and emptying arrays instead of deleting keys; enabling cloud_ops purely for cost monitoring without wanting IaC tooling; overlay configs that concatenate/override lists and end up writing an empty list over the populated default.","solutions":["Set at least one tool identifier: `iac_tools = [\"terraform\"]` under [cloud_ops]","If you do not use IaC tooling, set `[cloud_ops] enabled = false` so the whole guard block is skipped","Audit config layers (base file, profiles, overlays, ZEROCLAW_* env mirrors) for a layer that overrides iac_tools with an empty list after the base sets it","While fixing, verify default_cloud, supported_clouds, and cost_threshold_monthly_usd too — those guards run first and often fail together once cloud_ops is enabled"],"exampleFix":"# before\n[cloud_ops]\nenabled = true\niac_tools = []\n\n# after\n[cloud_ops]\nenabled = true\niac_tools = [\"terraform\", \"pulumi\"]","handlingStrategy":"validation","validationCode":"fn cloud_ops_precheck(cfg: &zeroclaw_config::Config) -> Result<(), String> {\n    let ops = &cfg.cloud_ops;\n    if ops.enabled && ops.iac_tools.is_empty() {\n        return Err(\"cloud_ops.iac_tools must not be empty when cloud_ops is enabled\".into());\n    }\n    Ok(())\n}","typeGuard":"fn has_iac_tools_when_enabled(cfg: &zeroclaw_config::Config) -> bool {\n    !cfg.cloud_ops.enabled || !cfg.cloud_ops.iac_tools.is_empty()\n}","tryCatchPattern":"match config.validate() {\n    Err(err) if err.to_string().contains(\"cloud_ops.iac_tools\") => {\n        // populate iac_tools or disable [cloud_ops], then reload the config\n    }\n    other => other?,\n}","preventionTips":["Keep a known-good [cloud_ops] block in the base config and toggle only `enabled`","Run Config::validate() on every config change in CI before deploy","In overlays, omit iac_tools to inherit defaults instead of writing []"],"tags":["configuration","validation","cloud","zeroclaw","rust"],"backgroundTag":"required-config-field-missing","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}