rust-lang/cargo · error · anyhow::Error
config.json not found
Error message
config.json not found
What it means
The HTTP/sparse registry exposes a `config.json` at its index root describing protocol version, supported fields, and auth requirements. `HttpRegistry::config()` (src/sources/registry/http_remote.rs:100) calls `config_opt()` and, when it yields `None` (no config could be fetched or read from cache), returns this error. Without `config.json` the sparse registry cannot proceed.
Source
Thrown at src/sources/registry/http_remote.rs:102
source_id: SourceId,
gctx: &'gctx GlobalContext,
name: &str,
) -> CargoResult<HttpRegistry<'gctx>> {
Ok(HttpRegistry {
name: name.into(),
registry_config: Mutex::new(None),
inner: HttpBackend::new(source_id, gctx, name)?,
})
}
fn inner(&self) -> &HttpBackend<'gctx> {
&self.inner
}
/// Get the registry configuration from either cache or remote.
async fn config(&self) -> CargoResult<RegistryConfig> {
let Some(config) = self.config_opt().await? else {
return Err(anyhow::anyhow!("config.json not found"));
};
Ok(config)
}
/// Get the registry configuration from either cache or remote.
/// Returns None if the config is not available.
async fn config_opt(&self) -> CargoResult<Option<RegistryConfig>> {
let mut config = self.registry_config.lock().await;
if let Some(config) = &*config
&& self.inner().is_fresh(RegistryConfig::NAME)
{
Ok(Some(config.clone()))
} else {
let result = self.config_opt_inner().await?;
*config = result.clone();
Ok(result)
}
}View on GitHub (pinned to 0e07a15537)
Solutions
- Open the index URL in a browser/curl and confirm `config.json` is served with HTTP 200 and valid JSON.
- If the registry is not sparse-capable, drop the `sparse+` prefix (use the git index protocol) or switch to a host that supports sparse.
- Fix network/proxy/TLS issues so the index root is reachable; remove a stale/empty cached config under `~/.cargo/registry/index/` and retry online.
- For a private registry, ensure auth credentials (`CARGO_REGISTRIES_<name>_TOKEN` / `[registries.<name>]`) are valid — a 401 can manifest as no config.
Example fix
# before [registries.my-reg] index = "sparse+https://example.com/index/" # server returns 404 for config.json # after: use the real sparse-capable index (or drop sparse+) [registries.my-reg] index = "sparse+https://index.example.com/"
Defensive patterns
Strategy: validation
Validate before calling
# Verify the sparse registry actually serves config.json before configuring it. curl -fsS "<index-url>/config.json" | head # (HTTP 200 + valid JSON => safe to use as sparse+<index-url>)
Prevention
- Confirm `config.json` is reachable before pointing cargo at a `sparse+` URL.
- Provide valid auth for private registries so 401 doesn't masquerade as missing config.
- Populate the cached config online before attempting offline builds.
When it happens
Trigger: A sparse registry URL (`sparse+https://...`) whose server doesn't serve `config.json` (404/403/5xx); first contact with a sparse registry while offline so the file was never cached; a typo'd sparse index URL pointing at a non-registry host; TLS / proxy / DNS failure contacting the index root.
Common situations: Pointing a `[registries]` entry at a `sparse+https://` URL that isn't actually a sparse registry; a private registry server misconfigured to omit `config.json`; corporate proxy blocking the index host; offline build that never populated the cached config.
Related errors
- sparse registry url must end in a slash `/`: {url}
- remote registries must have config
- can't checkout from '{}': you are in the offline mode ({offl
- failed to verify the checksum of `{}`
- non UTF8 path: {}
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/fb7e912881c6c0ad.json.
Report an issue: GitHub.