nikivdev/code · error

lifecycle.domains.host is required when remove_on_down=true

Error message

lifecycle.domains.host is required when remove_on_down=true

What it means

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.

Solutions

  1. Set lifecycle.domains.host to the primary host to remove on teardown
  2. Or set remove_on_down=false if routes should persist after down
  3. If the host differs per environment, supply it via env/config overrides
  4. Remember aliases' hosts are removed separately; the top-level host is still required

Example fix

// before
domains:
  remove_on_down: true
// after
domains:
  host: "app.test"
  remove_on_down: true
Defensive patterns

Strategy: validation

Validate before calling

fn can_remove_on_down(cfg: &LifecycleDomainsConfig) -> Result<(), String> {
    if cfg.remove_on_down.unwrap_or(false)
        && cfg.host.as_deref().map(str::trim).filter(|v| !v.is_empty()).is_none()
    {
        return Err("domains.host required when remove_on_down=true".into());
    }
    Ok(())
}

Prevention

When it happens

Trigger: Calling `run down` with lifecycle.domains.remove_on_down=true but no (or an empty) lifecycle.domains.host value.

Common situations: 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.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/00074c07c4370494. Report an issue: GitHub.

Appendix: source

Thrown at src/lifecycle.rs:167

    })?;

    println!("Lifecycle domains ready: http://{}", host);

    Ok(())
}

fn lifecycle_preferred_url(cfg: &LifecycleDomainsConfig) -> Option<String> {
    let host = lifecycle_domain_host(cfg).ok()?;
    Some(format!("http://{}", host))
}

fn run_domains_down(cfg: &LifecycleDomainsConfig) -> Result<bool> {
    let mut changed = false;
    let engine = parse_domains_engine(cfg.engine.as_deref())?;

    if cfg.remove_on_down.unwrap_or(false) {
        let host = lifecycle_domain_host(cfg)
            .map_err(|_| anyhow!("lifecycle.domains.host is required when remove_on_down=true"))?;
        remove_lifecycle_route(engine, host)?;
        for alias in &cfg.aliases {
            let alias_host = alias
                .host
                .as_deref()
                .map(str::trim)
                .filter(|v| !v.is_empty())
                .ok_or_else(|| {
                    anyhow!("lifecycle.domains.aliases[].host is required when remove_on_down=true")
                })?;
            remove_lifecycle_route(engine, alias_host)?;
        }
        changed = true;
    }

    if cfg.stop_proxy_on_down.unwrap_or(false) {
        domains::run(DomainsCommand {
            engine,

View on GitHub (pinned to a747e741ae)