zeroclaw-labs/zeroclaw · error · anyhow::Error
plugin registry returned HTTP {status} for {registry_url}
Error message
plugin registry returned HTTP {status} for {registry_url} What it means
The plugin registry index fetch succeeded at the transport level but returned a non-success HTTP status. This is the generic branch: any status other than 2xx that is not the special-cased default-URL 404 (error 1406) bails here with the concrete status code and URL.
Source
Thrown at src/plugin_registry.rs:69
|| source.contains('\\')
}
pub(crate) fn looks_like_url(source: &str) -> bool {
source.contains("://")
}
pub(crate) async fn fetch_registry_index(registry_url: &str) -> Result<PluginRegistryIndex> {
let response = reqwest::get(registry_url)
.await
.with_context(|| format!("fetching plugin registry {registry_url}"))?;
let status = response.status();
if !status.is_success() {
if status == reqwest::StatusCode::NOT_FOUND && registry_url == DEFAULT_REGISTRY_URL {
bail!(
"the public plugin registry is not populated yet; use --registry <url> to point at a custom registry"
);
}
bail!("plugin registry returned HTTP {status} for {registry_url}");
}
response
.json::<PluginRegistryIndex>()
.await
.context("parsing plugin registry JSON")
}
pub(crate) async fn download_registry_plugin(
registry_url: &str,
source: &str,
cache_data_dir: Option<&Path>,
) -> Result<DownloadedPlugin> {
let index = fetch_registry_index(registry_url).await?;
if let Some(data_dir) = cache_data_dir {
write_cached_registry_index(data_dir, registry_url, &index)?;
}
let spec = parse_plugin_spec(source)?;
let entry = resolve_entry(&index, &spec)?.clone();View on GitHub (pinned to 88bb9c8533)
Solutions
- Check the status code in the message: 404 means the URL/path is wrong, 401/403 means credentials are needed, 429/5xx means back off and retry
- Verify the registry URL resolves and serves the index (curl -I <url>)
- Add a secret/token mechanism if the registry requires auth — do not bake tokens into the URL in shared configs
- Retry with backoff for 429/5xx; the index fetch is idempotent
Example fix
# before zeroclaw plugin install p --registry https://reg.example/plugins # 404 # after curl -I https://reg.example/registry/index.json # confirm 200 zeroclaw plugin install p --registry https://reg.example/registry/index.json
Defensive patterns
Strategy: retry
Validate before calling
// Cheap reachability + status probe of the registry before running installs:
let s = reqwest::get(®istry_url).await?.status();
if !s.is_success() { /* skip/defer install, alert on 5xx, fix URL on 404 */ } Try / catch
// Retry with exponential backoff ONLY for 429/5xx; treat 401/403 as config
// errors (credentials) and 404 as a wrong URL. Parse the numeric status from
// the 'plugin registry returned HTTP {status}' message. Prevention
- Cache the registry index locally between runs
- Rate-limit install jobs to avoid 429 in CI
- Validate custom registry URLs once at config load
When it happens
Trigger: GET on the registry index URL returning 401/403 (auth required), 404 for a custom registry (wrong path), 429 (rate limit), 5xx (registry down), or a redirect chain ending in an error. Triggered by download_registry_plugin via fetch_registry_index.
Common situations: Typo'd or outdated --registry URL (404); private registry needing a token (401/403); rate-limited CI hitting the registry repeatedly (429); registry outage or maintenance (502/503).
Related errors
- the public plugin registry is not populated yet; use --regis
- plugin archive returned HTTP {status} for {url}
- channel does not support room creation
- elicitation returned unknown choice const: {s}
- purge_namespace not supported by this memory backend
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/9f4869569c33d83d.
Report an issue: GitHub.