Hmbown/CodeWhale · error

fleet alert adapter is not configured

Error message

fleet alert adapter {} is not configured

What it means

FleetAlertDispatcher::dispatch() routes each FleetAlertEvent through config.routes whose event class matches. Each route names an adapter by string key, and that key must exist in the config.adapters map (kind: slack | webhook | pagerduty entries). If the route's adapter string has no matching adapters entry, dispatch fails immediately with this error.

Solutions

  1. Open the fleet alerts config and make the route's adapter string byte-identical to an existing key under adapters.
  2. If the adapter was meant to exist, add the missing adapters entry (Slack{webhook_env}, Webhook{url_env,secret_env}, or PagerDuty{routing_key_env}).
  3. Remove the stale route if the adapter was retired.
  4. Until config is fixed, you can set enabled=false or use dry_run=true so dispatch returns early instead of erroring.

Example fix

// before
{"enabled":true,"routes":[{"events":["task_failed"],"adapter":"slack-ops"}],"adapters":{"slack":{"kind":"slack","webhook_env":"SLACK_WEBHOOK_URL"}}}

// after (route key matches adapters key)
{"enabled":true,"routes":[{"events":["task_failed"],"adapter":"slack"}],"adapters":{"slack":{"kind":"slack","webhook_env":"SLACK_WEBHOOK_URL"}}}
Defensive patterns

Strategy: validation

Validate before calling

fn validate_alert_config(cfg: &FleetAlertConfig) -> Result<(), String> {
    for route in &cfg.routes {
        if !cfg.adapters.contains_key(&route.adapter) {
            return Err(format!("route references unknown adapter '{}'", route.adapter));
        }
    }
    Ok(())
}

validate_alert_config(&config)?; // before enabling dispatch

Type guard

fn adapter_is_configured(cfg: &FleetAlertConfig, route: &FleetAlertRoute) -> bool {
    cfg.adapters.contains_key(&route.adapter)
}

Try / catch

match dispatcher.dispatch(&event) {
    Ok(deliveries) => { /* record deliveries */ }
    Err(e) if e.to_string().contains("adapter") && e.to_string().contains("not configured") => {
        // config defect: log route/adapter names, disable the route, continue the run
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A FleetAlertConfig where routes[].adapter (e.g. "ops-slack") does not match any key in the adapters BTreeMap — typo, renamed adapter, route copied from another config, or adapter entry deleted while the route stayed.

Common situations: Hand-edited fleet alert TOML/JSON config; renaming an adapter key without updating routes; enabling alert routes via config merge where the adapters section comes from a different file; CI configs drifting from local ones.

Related errors


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

Appendix: source

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

    R: FleetAlertSecretResolver,
{
    pub fn new(config: FleetAlertConfig, resolver: R) -> Self {
        Self { config, resolver }
    }

    pub fn dispatch(&self, event: &FleetAlertEvent) -> Result<Vec<FleetAlertDelivery>> {
        if !self.config.enabled {
            return Ok(Vec::new());
        }
        let mut deliveries = Vec::new();
        for route in self
            .config
            .routes
            .iter()
            .filter(|route| route_matches(route, event.class))
        {
            let adapter = self.config.adapters.get(&route.adapter).ok_or_else(|| {
                anyhow!("fleet alert adapter {} is not configured", route.adapter)
            })?;
            let prepared = prepare_alert(&route.adapter, adapter, event, self.config.dry_run)?;
            let sent = if self.config.dry_run {
                false
            } else {
                send_alert(adapter, &prepared.body, &self.resolver)?
            };
            deliveries.push(FleetAlertDelivery {
                adapter: route.adapter.clone(),
                event_class: event.class,
                dry_run: self.config.dry_run,
                sent,
                redacted_payload: prepared.redacted_payload,
            });
        }
        Ok(deliveries)
    }
}

View on GitHub (pinned to 0c42157ee5)