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

plugin archive returned HTTP {status} for {url}

Error message

plugin archive returned HTTP {status} for {url}

What it means

A plugin archive download (the zip artifact referenced by a registry entry) returned a non-success HTTP status. download_archive_bytes GETs the archive URL from the registry entry and bails with the exact status and URL on any non-2xx response.

Source

Thrown at src/plugin_registry.rs:111

    extract_zip_safe(std::io::Cursor::new(bytes), &extract_dir)?;
    let plugin_dir = find_manifest_dir(&extract_dir)?;
    let manifest = load_plugin_manifest(&plugin_dir)?;
    verify_manifest_matches_registry(&entry, &manifest)?;

    Ok(DownloadedPlugin {
        _temp_dir: temp_dir,
        plugin_dir,
        manifest,
    })
}

async fn download_archive_bytes(url: &str) -> Result<Vec<u8>> {
    let mut response = reqwest::get(url)
        .await
        .with_context(|| format!("downloading plugin archive {url}"))?;
    let status = response.status();
    if !status.is_success() {
        bail!("plugin archive returned HTTP {status} for {url}");
    }
    if let Some(len) = response.content_length()
        && len > MAX_PLUGIN_ZIP_BYTES as u64
    {
        bail!("plugin archive exceeds maximum size of {MAX_PLUGIN_ZIP_BYTES} bytes");
    }

    let mut bytes = Vec::new();
    while let Some(chunk) = response
        .chunk()
        .await
        .context("reading plugin archive response body")?
    {
        append_chunk_capped(&mut bytes, &chunk, MAX_PLUGIN_ZIP_BYTES)?;
    }
    Ok(bytes)
}

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Confirm the artifact URL from the error is actually reachable: curl -I <url>
  2. Re-fetch the registry index (it may be stale and reference old artifact paths) and retry the install
  3. If you publish the registry, re-upload the archive and republish the index together so entry URL and artifact stay in sync
  4. Retry after a wait for 429/5xx artifact-host errors

Example fix

# before
# registry entry: { "url": "https://cdn/old/p-0.2.0.zip" }  -> 404
zeroclaw plugin install p

# after
# republish index with corrected url, then:
zeroclaw plugin install p --registry https://reg/registry/index.json
Defensive patterns

Strategy: retry

Validate before calling

// HEAD the archive URL from the registry entry before install:
let resp = reqwest::head(&entry.url).await?;
if !resp.status().is_success() { /* defer install; report stale entry */ }

Try / catch

// Retry transient 5xx/429 on 'plugin archive returned HTTP' failures; on 404
// refresh the registry index once and retry, then give up with a clear report.

Prevention

When it happens

Trigger: Calling plugin install where the registry index loaded fine but the archive URL inside it is broken: 404 (artifact not uploaded / moved), 403 (expired pre-signed link), 429, or 5xx on the artifact host.

Common situations: Registry index is newer/older than the storage: entry points at an artifact that was deleted or not yet uploaded; CDN/auth link expired; artifact host outage; mirror serving metadata but not binaries.

Related errors


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