Hmbown/CodeWhale · error

fleet alert URL is not configured

Error message

fleet alert URL {name} is not configured

What it means

required_https_url() resolves a Webhook alert adapter's url_env variable through the secret resolver (env var, non-empty required). If the variable is absent or empty, resolve returns None and this error fires, naming the expected env var. It fires before URL syntax or scheme checks, so a set-but-malformed URL produces a different error.

Solutions

  1. Export a non-empty HTTPS URL under the exact name in url_env in the process environment that dispatches alerts.
  2. Check 'env | grep <name>' inside that same context (systemd 'Environment=', tmux session, CI secret) rather than your editor shell.
  3. Keep dry_run=true in environments that intentionally have no webhook target — dry-run does not hit the URL requirement path the same way.
  4. If multiple adapters need the same endpoint, point all url_env fields at one variable name and set it once.

Example fix

# before
# adapters: {"hook":{"kind":"webhook","url_env":"ALERT_HOOK_URL"}}
$ ./run-fleet.sh        # ALERT_HOOK_URL unset -> error

# after
$ ALERT_HOOK_URL="https://hooks.example.com/fleet" ./run-fleet.sh
Defensive patterns

Strategy: validation

Validate before calling

fn webhook_urls_resolvable(cfg: &FleetAlertConfig) -> Result<(), String> {
    for (name, adapter) in &cfg.adapters {
        if let FleetAlertAdapterConfig::Webhook { url_env, .. } = adapter {
            if std::env::var(url_env).map(|v| v.is_empty()).unwrap_or(true) {
                return Err(format!("webhook adapter '{name}' needs non-empty env {url_env}"));
            }
        }
    }
    Ok(())
}

Try / catch

match dispatcher.dispatch(&event) {
    Err(e) if e.to_string().contains("URL") && e.to_string().contains("not configured") => {
        // env var named in message is missing in this process; log and degrade (skip alert)
    }
    other => other.map(|_| ())?,
}

Prevention

When it happens

Trigger: A Webhook adapter (kind: webhook with url_env: "FLEET_WEBHOOK_URL") dispatched with dry_run=false while FLEET_WEBHOOK_URL is unset, exported as empty, or defined only in a parent shell the process never inherited.

Common situations: Secrets managed per-shell but fleet runs from a daemon, launcher, or CI job; renaming the env var in config without updating deployment environment; multiple webhook adapters sharing one url_env name where one deployment forgot it.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/b56724963868014e. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/fleet/alerts.rs:498

    }
}

fn required_secret<R>(resolver: &R, name: &str) -> Result<String>
where
    R: FleetAlertSecretResolver,
{
    resolver
        .resolve(name)
        .ok_or_else(|| anyhow!("fleet alert secret {name} is not configured"))
}

fn required_https_url<R>(resolver: &R, name: &str) -> Result<String>
where
    R: FleetAlertSecretResolver,
{
    let url = resolver
        .resolve(name)
        .ok_or_else(|| anyhow!("fleet alert URL {name} is not configured"))?;
    validate_https_alert_url(name, &url)?;
    Ok(url)
}

fn validate_https_alert_url(name: &str, url: &str) -> Result<()> {
    let parsed = reqwest::Url::parse(url)
        .with_context(|| format!("fleet alert URL from {name} is not a valid URL"))?;
    if parsed.scheme() != "https" {
        return Err(anyhow!("fleet alert URL from {name} must use https"));
    }
    Ok(())
}

fn short_reason(reason: &str) -> String {
    let trimmed = reason.trim();
    if trimmed.len() <= 240 {
        return trimmed.to_string();
    }

View on GitHub (pinned to 0c42157ee5)