{"record":{"id":"00074c07c4370494","repo":"nikivdev/code","slug":"lifecycle-domains-host-is-required-when-remove-on","errorCode":null,"errorMessage":"lifecycle.domains.host is required when remove_on_down=true","messagePattern":"lifecycle\\.domains\\.host is required when remove_on_down=true","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lifecycle.rs","lineNumber":167,"sourceCode":"    })?;\n\n    println!(\"Lifecycle domains ready: http://{}\", host);\n\n    Ok(())\n}\n\nfn lifecycle_preferred_url(cfg: &LifecycleDomainsConfig) -> Option<String> {\n    let host = lifecycle_domain_host(cfg).ok()?;\n    Some(format!(\"http://{}\", host))\n}\n\nfn run_domains_down(cfg: &LifecycleDomainsConfig) -> Result<bool> {\n    let mut changed = false;\n    let engine = parse_domains_engine(cfg.engine.as_deref())?;\n\n    if cfg.remove_on_down.unwrap_or(false) {\n        let host = lifecycle_domain_host(cfg)\n            .map_err(|_| anyhow!(\"lifecycle.domains.host is required when remove_on_down=true\"))?;\n        remove_lifecycle_route(engine, host)?;\n        for alias in &cfg.aliases {\n            let alias_host = alias\n                .host\n                .as_deref()\n                .map(str::trim)\n                .filter(|v| !v.is_empty())\n                .ok_or_else(|| {\n                    anyhow!(\"lifecycle.domains.aliases[].host is required when remove_on_down=true\")\n                })?;\n            remove_lifecycle_route(engine, alias_host)?;\n        }\n        changed = true;\n    }\n\n    if cfg.stop_proxy_on_down.unwrap_or(false) {\n        domains::run(DomainsCommand {\n            engine,","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/lifecycle.rs#L149-L185","documentation":"run_domains_down removes the domain route on teardown only if remove_on_down is true, in which case a host is mandatory. When lifecycle_domain_host(cfg) fails (no host configured), it converts the failure into this explicit error explaining the requirement.","triggerScenarios":"Calling `run down` with lifecycle.domains.remove_on_down=true but no (or an empty) lifecycle.domains.host value.","commonSituations":"Enabling remove_on_down in CI or a copied config without setting the host; host set only on aliases but not on the top-level domains config; whitespace-only host value.","solutions":["Set lifecycle.domains.host to the primary host to remove on teardown","Or set remove_on_down=false if routes should persist after down","If the host differs per environment, supply it via env/config overrides","Remember aliases' hosts are removed separately; the top-level host is still required"],"exampleFix":"// before\ndomains:\n  remove_on_down: true\n// after\ndomains:\n  host: \"app.test\"\n  remove_on_down: true","handlingStrategy":"validation","validationCode":"fn can_remove_on_down(cfg: &LifecycleDomainsConfig) -> Result<(), String> {\n    if cfg.remove_on_down.unwrap_or(false)\n        && cfg.host.as_deref().map(str::trim).filter(|v| !v.is_empty()).is_none()\n    {\n        return Err(\"domains.host required when remove_on_down=true\".into());\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat remove_on_down=true and host as a coupled pair — set both or neither","Validate teardown config during `up` so problems surface early","Don't rely on alias hosts as a substitute for the top-level host","Add a config check to CI for lifecycle settings"],"tags":["config","validation","lifecycle","domains","teardown"],"backgroundTag":"missing-required-config-field","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}