zeroclaw-labs/zeroclaw · warning · anyhow::Error
non-success status {}
Error message
non-success status {} What it means
Inside discord_thread_parent, a GET /channels/{channel_id} with the bot token returns non-2xx and bails with this bare status text. The caller wraps the lookup in a timeout and converts any Err — including this one — into a DEBUG log and a cached None, so thread-parent resolution silently degrades and the error never propagates outward. Common statuses: 403 Missing Permissions (bot lacks VIEW_CHANNELS), 404 (deleted channel or malformed id), 401 (bad token).
Source
Thrown at crates/zeroclaw-channels/src/discord/mod.rs:1520
let url = format!("https://discord.com/api/v10/channels/{channel_id}");
let lookup = async {
let resp = client
.get(&url)
.header("Authorization", format!("Bot {bot_token}"))
.send()
.await
.map_err(|e| {
::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!({"error": format!("{}", e)})),
"request failed"
);
anyhow::Error::msg(format!("request failed: {e}"))
})?;
if !resp.status().is_success() {
anyhow::bail!("non-success status {}", resp.status());
}
let body: serde_json::Value = resp.json().await.map_err(|e| {
::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!({"error": format!("{}", e)})),
"body parse failed"
);
anyhow::Error::msg(format!("body parse failed: {e}"))
})?;
let is_thread = body
.get("type")
.and_then(serde_json::Value::as_u64)
.map(is_thread_channel_type)
.unwrap_or(false);
Ok::<Option<String>, anyhow::Error>(if is_thread {
body.get("parent_id")View on GitHub (pinned to 88bb9c8533)
Solutions
- Grant the bot VIEW_CHANNELS on channels where thread routing matters (channel and role overrides)
- Treat as non-fatal — the code already degrades to no thread parent; fixing permissions restores resolution
- If 404s dominate, verify channel ids come from gateway events, not user input
- If every lookup 401s, the bot token itself is invalid
Defensive patterns
Strategy: fallback
Validate before calling
// Validate the bot token once at startup so 401s are impossible mid-run:
// GET https://discord.com/api/v10/users/@me with `Bot {token}` must return 200.
// The lookup itself already degrades to a cached None on any error. Prevention
- Grant VIEW_CHANNELS on every channel the bot serves
- Watch the DEBUG 'channel lookup failed' logs to catch permission drift
- Take channel ids from gateway events, never user input
When it happens
Trigger: Bot invited without View Channel on the target channel; channel deleted between message receipt and lookup; a sentinel or malformed id passed as a channel id (guaranteed non-2xx); bot token revoked mid-session.
Common situations: Locked/private channels where the bot receives gateway events but cannot fetch the channel object; bot removed from a guild while its threads still process; permission reorganizations by server admins.
Related errors
- Discord add reaction failed ({status}): {err}
- channels.discord.{alias}.bot_token is unset but the channel
- unsupported room visibility '{other}': expected private or p
- channel '{}' does not support forge API requests
- channel does not support room invites
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/ba1ad6db1ce0a977.
Report an issue: GitHub.