zeroclaw-labs/zeroclaw · error · anyhow::Error

Discord gate-prompt finalize failed ({status})

Error message

Discord gate-prompt finalize failed ({status})

What it means

finalize_gate_prompt PATCHes each recorded gate-prompt message on Discord (appending the outcome under the original description and clearing the buttons via an explicit empty components array). When Discord answers non-2xx, the failed record and all unattempted records are put back into the process-wide gate_prompts registry and the function bails. A later terminal event (e.g. a stale button click's 'window has passed') retries the finalize.

Source

Thrown at crates/zeroclaw-channels/src/discord/mod.rs:4049

            // Transient failure: put the failed and unattempted records back so a
            // later terminal event (a stale click's "window has passed") retries.
            let resp = match resp {
                Ok(resp) => resp,
                Err(e) => {
                    gate_prompts::record(reference, record);
                    for remaining in records {
                        gate_prompts::record(reference, remaining);
                    }
                    return Err(e.into());
                }
            };
            if !resp.status().is_success() {
                let status = resp.status();
                gate_prompts::record(reference, record);
                for remaining in records {
                    gate_prompts::record(reference, remaining);
                }
                anyhow::bail!("Discord gate-prompt finalize failed ({status})");
            }
        }
        Ok(true)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn effective_recipient_prefers_per_message_target() {
        let ids = vec!["fallback_channel".to_string()];
        assert_eq!(
            effective_discord_recipient("explicit_channel", &ids),
            Some("explicit_channel")
        );
    }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Read the embedded status: 404 means the prompt message is gone; prune that reference's gate-prompt records if you operate the registry, otherwise it will keep failing
  2. 403 → re-grant the bot View Channel / Send Messages / Read Message History in the prompt channel and let the next terminal event retry
  3. 401 → restore a valid bot token and reconnect; records were preserved so finalize retries
  4. 5xx → do nothing: records were re-recorded and a later event retries the PATCH
Defensive patterns

Strategy: retry

Try / catch

match channel.finalize_gate_prompt(reference, outcome).await {
    Ok(_) => {}
    Err(e) if e.to_string().contains("gate-prompt finalize failed") => {
        // records were re-recorded by the channel; retry happens on the next terminal event
        tracing::warn!("gate-prompt finalize deferred: {e}");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: The PATCH to /channels/{channel_id}/messages/{message_id} returns non-success while finalizing: 403 (bot lost Send Messages / edit permission in that channel), 404 (prompt message deleted), 401 (bot token reset), or a 5xx.

Common situations: A moderator deletes the approval prompt before the agent answers; the bot is kicked from the guild or loses channel permissions mid-flow; the bot token is regenerated while prompts are pending; transient Discord 5xx.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/7f163e99f8178981. Report an issue: GitHub.