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
- Confirm the artifact URL from the error is actually reachable: curl -I <url>
- Re-fetch the registry index (it may be stale and reference old artifact paths) and retry the install
- If you publish the registry, re-upload the archive and republish the index together so entry URL and artifact stay in sync
- 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
- Publish index and artifact atomically if you run a registry
- Use stable, non-expiring artifact URLs (avoid short-lived signed links)
- Verify artifact URLs in registry lint checks
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
- elicitation returned unknown choice const: {s}
- plugin registry returned HTTP {status} for {registry_url}
- channel does not support room creation
- purge_namespace not supported by this memory backend
- attachment download failed ({status}): {body}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/0f9dc43854f6c4c4.
Report an issue: GitHub.