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

  1. Open the index URL in a browser/curl and confirm `config.json` is served with HTTP 200 and valid JSON.
  2. If the registry is not sparse-capable, drop the `sparse+` prefix (use the git index protocol) or switch to a host that supports sparse.
  3. Fix network/proxy/TLS issues so the index root is reachable; remove a stale/empty cached config under `~/.cargo/registry/index/` and retry online.
  4. 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

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


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/fb7e912881c6c0ad.json. Report an issue: GitHub.