{"record":{"id":"1c6903006cd0047b","repo":"Hmbown/CodeWhale","slug":"fleet-alert-adapter-is-not-configured-alerts","errorCode":null,"errorMessage":"Fleet alert adapter {} is not configured","messagePattern":"Fleet alert adapter (.+?) is not configured","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/fleet/alerts.rs","lineNumber":133,"sourceCode":"    R: FleetAlertSecretResolver,\n{\n    pub fn new(config: FleetAlertConfig, resolver: R) -> Self {\n        Self { config, resolver }\n    }\n\n    pub fn dispatch(&self, event: &FleetAlertEvent) -> Result<Vec<FleetAlertDelivery>> {\n        if !self.config.enabled {\n            return Ok(Vec::new());\n        }\n        let mut deliveries = Vec::new();\n        for route in self\n            .config\n            .routes\n            .iter()\n            .filter(|route| route_matches(route, event.class))\n        {\n            let adapter = self.config.adapters.get(&route.adapter).ok_or_else(|| {\n                anyhow!(\"Fleet alert adapter {} is not configured\", route.adapter)\n            })?;\n            let prepared = prepare_alert(&route.adapter, adapter, event, self.config.dry_run)?;\n            let sent = if self.config.dry_run {\n                false\n            } else {\n                send_alert(adapter, &prepared.body, &self.resolver)?\n            };\n            deliveries.push(FleetAlertDelivery {\n                adapter: route.adapter.clone(),\n                event_class: event.class,\n                dry_run: self.config.dry_run,\n                sent,\n                redacted_payload: prepared.redacted_payload,\n            });\n        }\n        Ok(deliveries)\n    }\n}","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/fleet/alerts.rs#L115-L151","documentation":"The Fleet alert dispatcher routes an event to adapters by name using the configured routes. Each route's `adapter` must be a key present in `self.config.adapters`; a route referencing an unconfigured adapter is a misconfiguration, so dispatch fails rather than silently dropping the alert.","triggerScenarios":"Calling `dispatch` on a Fleet alert dispatcher whose config contains a route whose `route.adapter` name has no matching entry in `config.adapters`.","commonSituations":"Typo in an adapter name in the routes section; an adapter definition removed or renamed while routes still reference the old name; YAML/TOML config indentation placing the adapter under the wrong key.","solutions":["Add an adapter definition with the name referenced by the route to config.adapters.","Fix the route's adapter field to match an existing adapter key exactly (check spelling/case).","Remove the stale route if the adapter was intentionally retired."],"exampleFix":"# before\nroutes:\n  - class: build-failure\n    adapter: slack-ops\n# after: either rename the route adapter or define it\nadapters:\n  slack-ops:\n    kind: webhook\n    ...","handlingStrategy":"validation","validationCode":"fn validate_alert_config(config: &FleetAlertsConfig) -> Result<()> {\n    for route in &config.routes {\n        anyhow::ensure!(\n            config.adapters.contains_key(&route.adapter),\n            \"route references unconfigured adapter {}\",\n            route.adapter\n        );\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match dispatcher.dispatch(&event).await {\n    Err(e) if e.to_string().contains(\"is not configured\") => {\n        log::warn!(\"alert dropped, adapter missing: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Validate alert config (routes vs adapters) at load time, before dispatching.","Keep adapter names in one constants module to avoid typos.","Rename adapters and routes together in a single config change."],"tags":["fleet","alerts","config","routing"],"backgroundTag":"missing-required-config-field","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}