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

channel does not support room creation

Error message

channel does not support room creation

What it means

check() (src/commands/update.rs:119) GETs the GitHub releases API — https://api.github.com/repos/zeroclaw-labs/zeroclaw/releases/latest, or /releases/tags/v<tag> when a --version is pinned — with an unauthenticated client (UA zeroclaw/<version>, 15s timeout) and bails on any non-2xx status, echoing the raw status. Reachability failures are a different error ("failed to reach GitHub releases API"); this one means GitHub answered but refused. Both `zeroclaw update` and update checks run through this function.

Source

Thrown at crates/zeroclaw-api/src/channel.rs:904

    /// Unpin a previously pinned message.
    async fn unpin_message(&self, _channel_id: &str, _message_id: &str) -> anyhow::Result<()> {
        Ok(())
    }

    /// Redact (delete) a message from the channel.
    async fn redact_message(
        &self,
        _channel_id: &str,
        _message_id: &str,
        _reason: Option<String>,
    ) -> anyhow::Result<()> {
        Ok(())
    }

    /// Create a new platform room/conversation when the channel supports it.
    async fn create_room(&self, _options: &RoomCreationOptions) -> anyhow::Result<String> {
        anyhow::bail!("channel does not support room creation")
    }

    /// Invite a user to an existing platform room/conversation.
    async fn invite_user(&self, _room_id: &str, _user_id: &str) -> anyhow::Result<()> {
        anyhow::bail!("channel does not support room invites")
    }

    /// Request interactive tool-call approval from the channel operator.
    ///
    /// Returns `Ok(Some(response))` when the operator answers within the
    /// channel's configured `approval_timeout_secs`; timeouts surface as
    /// `Deny`. Returns `Ok(None)` only for channels that do not implement
    /// the prompt at all — the caller falls back to its default policy
    /// (typically auto-deny).
    async fn request_approval(
        &self,
        _recipient: &str,
        _request: &ChannelApprovalRequest,

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. If 403: you hit the unauthenticated rate limit — wait for the window to reset and retry (curl -I the API URL and check x-ratelimit-reset)
  2. If 404 with --version: verify the tag exists on the releases page; drop --version to fetch latest
  3. Check https://www.githubstatus.com and your proxy/HTTPS_PROXY environment for 5xx or interception
  4. Retry `zeroclaw update --check` after a minute — transient statuses clear on their own

Example fix

// before
let info = update::check(None).await?; // dies on first 403 rate-limit

// after
let mut backoff = 30;
let info = loop {
    match update::check(None).await {
        Ok(i) => break i,
        Err(e) if e.to_string().contains("GitHub API returned 403") => {
            tokio::time::sleep(std::time::Duration::from_secs(backoff)).await;
            backoff *= 2;
        }
        Err(e) => return Err(e),
    }
};
Defensive patterns

Strategy: retry

Validate before calling

// Cheap preflight: confirm the releases API answers 200 before running update.
async fn releases_api_ok() -> bool {
    reqwest::Client::new()
        .get("https://api.github.com/repos/zeroclaw-labs/zeroclaw/releases/latest")
        .header("User-Agent", "preflight")
        .send()
        .await
        .map(|r| r.status().is_success())
        .unwrap_or(false)
}

Try / catch

match update::check(version).await {
    Err(e) => {
        let msg = e.to_string();
        if msg.contains("403") || msg.contains("429") {
            // Rate limited: sleep out the window (check x-ratelimit-reset), then retry once.
        } else if msg.contains("404") {
            // Permanent: the pinned tag does not exist — fail fast with a clear message.
        } else if msg.contains("5") /* 5xx */ {
            // Transient GitHub outage: retry with backoff.
        }
    }
    ok => ok,
}

Prevention

When it happens

Trigger: `zeroclaw update [--check]` or `zeroclaw update --version <v>` when GitHub returns 403 (unauthenticated rate limit of 60 req/h per IP exceeded), 404 (pinned tag does not exist or no releases published), or a 5xx outage. Also triggered by any caller of update::check().

Common situations: Shared CI runner or NAT egress IP that exhausted the unauthenticated rate limit; typo'd or yanked --version tag; GitHub incident; proxies that answer with 4xx on behalf of GitHub.

Related errors


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