zeroclaw-labs/zeroclaw · error
webhook-audit: {e}
Error message
webhook-audit: {e} What it means
Raised by agent_delete_precheck (src/alias_cli/mod.rs:454), the hard gate that runs before `zeroclaw agents delete <alias>` mutates any config or owned state. It opens the data_dir-backed AcpSessionStore (crates/zeroclaw-gateway/src/agent_owned_state.rs:13) and counts live Agent Client Protocol sessions owned by the alias; a count > 0 aborts the delete because removing the alias would orphan live WebSocket sessions on the gateway's `/acp` route. The check mirrors the gateway's own delete gate and fails closed: if the session store cannot even be read, deletion is also refused (context error "could not verify live ACP sessions"). Nothing has been modified when this error surfaces.
Source
Thrown at crates/zeroclaw-runtime/src/hooks/builtin/webhook_audit.rs:133
.with_attrs(::serde_json::json!({"hook": "webhook-audit"})),
"webhook-audit hook is enabled but no URL is configured — audit events will be dropped"
);
}
// Validate URL against SSRF if one is provided.
if !config.url.is_empty()
&& let Err(e) = validate_webhook_url(&config.url)
{
::zeroclaw_log::record!(
ERROR,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(
::serde_json::json!({"hook": "webhook-audit", "error": format!("{}", e)})
),
"webhook URL validation failed"
);
panic!("webhook-audit: {e}");
}
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(5))
.build()
.expect("failed to build webhook HTTP client");
Self {
config,
client,
pending_args: Arc::new(Mutex::new(HashMap::new())),
}
}
}
/// Simple glob matching: `*` matches any sequence of characters.
fn glob_matches(pattern: &str, text: &str) -> bool {
if pattern == "*" {
return true;View on GitHub (pinned to 88bb9c8533)
Solutions
- Disconnect the ACP clients using that agent (close the editor/TUI windows or tabs holding the session), then re-run `zeroclaw agents delete <alias>`
- If no client is visibly connected, stop the running zeroclaw gateway process (it owns the `/acp` WebSocket sessions), then retry the delete
- For scripted deletes, always stop or drain the gateway first so no `/acp` sessions can be live
- If it still refuses, inspect the ACP session store under data_dir for live rows owned by the alias and report stale rows as a bug rather than deleting state by hand
Example fix
# before $ zeroclaw agents delete writer Error: 2 live ACP session(s) for `writer` — end them first # after $ # 1. close the ACP clients (editor/TUI) using that agent $ # 2. stop the zeroclaw gateway (it owns the /acp WebSocket sessions) $ zeroclaw agents delete writer
Defensive patterns
Strategy: validation
Validate before calling
use zeroclaw_gateway::agent_owned_state::live_acp_session_count;
// Run the same gate the CLI precheck uses BEFORE attempting the delete.
fn agent_safe_to_delete(config: &Config, alias: &str) -> anyhow::Result<bool> {
Ok(live_acp_session_count(config, alias)? == 0)
} Try / catch
match alias_delete(&config, &alias).await {
Err(e) if e.to_string().contains("live ACP session(s)") => {
// Refusal, not a crash: surface it, have the operator close ACP
// clients / stop the gateway, then retry. Never delete session
// state by hand to force the delete through.
}
other => other,
} Prevention
- Close all ACP clients (editor/TUI integrations) for an agent before deleting it
- Run scripted agent deletions while the gateway is stopped or drained of /acp sessions
- Treat an unreadable session store as a refusal too — the precheck intentionally fails closed
- Remember the gateway's own delete API has the same gate, so both paths need the same sequencing
When it happens
Trigger: Running `zeroclaw agents delete <alias>` (after confirming/--yes) while an ACP client — an editor or TUI integration — holds an open `/acp` WebSocket session attributed to that alias, typically with the zeroclaw gateway running. Any state where count_live_sessions_by_agent(alias) returns > 0, including session rows not yet marked ended after an abrupt client exit while the gateway is still up.
Common situations: Deleting an agent from one terminal while an editor integration still has the agent's session open in another; automated cleanup scripts that run against a live gateway with connected ACP clients; stale live-session rows after a crashed client when the gateway process is still alive.
Related errors
- Unknown agent {agent_alias:?} (no [agents.{agent_alias}] ent
- unsupported room visibility '{other}': expected private or p
- channel '{}' does not support forge API requests
- ACP returned unexpected outcome: {other}
- ACP elicitation/create failed: {} ({})
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/e46a7aca529aecb4.
Report an issue: GitHub.