zeroclaw-labs/zeroclaw · error · anyhow::Error
unsupported delivery mode: {}
Error message
unsupported delivery mode: {} What it means
validate_delivery_config whitelists cron delivery modes: 'none' (case-insensitive) returns Ok immediately; 'announce' proceeds to require a channel; every other mode string bails. Webhook delivery is NOT a mode — webhook targets are configured under announce mode (validate_delivery_accepts_webhook_with_thread_id pins this), which is why mode='webhook' is rejected.
Source
Thrown at crates/zeroclaw-runtime/src/cron/mod.rs:145
agent_alias,
name,
schedule,
command,
delivery,
shell_output_format,
)
}
pub fn validate_delivery_config(delivery: Option<&DeliveryConfig>) -> Result<()> {
let Some(delivery) = delivery else {
return Ok(());
};
if delivery.mode.eq_ignore_ascii_case("none") {
return Ok(());
}
if !delivery.mode.eq_ignore_ascii_case("announce") {
bail!("unsupported delivery mode: {}", delivery.mode);
}
let channel = delivery.channel.as_deref().map(str::trim);
if channel.filter(|value| !value.is_empty()).is_none() {
bail!("delivery.channel is required for announce mode");
}
let has_target = delivery
.to
.as_deref()
.map(str::trim)
.is_some_and(|value| !value.is_empty());
if !has_target {
bail!("delivery.to is required for announce mode");
}
Ok(())
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Set delivery.mode to 'announce' (and provide delivery.channel) or 'none'
- For webhook delivery, keep mode 'announce' and configure the webhook target/thread id in the delivery target fields
- Check the cron config schema/docs for accepted mode and target fields
- Normalize the mode string (trim, lowercase) before validation if config sources may inject whitespace or casing
Example fix
// before
delivery = { mode: "webhook", channel: None }
// after
delivery = { mode: "announce", channel: Some("telegram:ops".into()), to: Some(target) } Defensive patterns
Strategy: validation
Validate before calling
if !delivery_is_valid(&delivery) {
anyhow::bail!("delivery.mode must be 'none' or 'announce' (webhooks are configured as announce targets)");
}
cron.add_shell_job(spec, delivery).await?; Type guard
fn is_supported_delivery_mode(mode: &str) -> bool {
matches!(mode.trim().to_ascii_lowercase().as_str(), "none" | "announce")
} Prevention
- Remember the vocabulary: modes are none/announce; webhooks are targets under announce
- Validate delivery blocks at config load, not only at job creation
- Normalize mode strings (trim + lowercase) before submission
- Pin the accepted modes in your config schema/docs
When it happens
Trigger: add_shell_job / add_agent_job / cron handle_command invoked with delivery.mode set to 'webhook', 'send', 'message', 'email', or a typo like 'anounce'. Case variants such as 'Announce' pass; any other token does not.
Common situations: Users assuming webhook is a first-class delivery mode; configs copied from other tools with different vocabularies; config drift across versions where docs/examples disagreed.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- delivery.channel is required for announce mode
- Unknown agent {agent_alias:?} (no [agents.{agent_alias}] ent
- unsupported room visibility '{other}': expected private or p
- channel '{}' does not support forge API requests
- Destination {} is not in allowed list
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/82f6e2007ceb882c.
Report an issue: GitHub.