{"record":{"id":"fb7e912881c6c0ad","repo":"rust-lang/cargo","slug":"config-json-not-found","errorCode":null,"errorMessage":"config.json not found","messagePattern":"config\\.json not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/registry/http_remote.rs","lineNumber":102,"sourceCode":"        source_id: SourceId,\n        gctx: &'gctx GlobalContext,\n        name: &str,\n    ) -> CargoResult<HttpRegistry<'gctx>> {\n        Ok(HttpRegistry {\n            name: name.into(),\n            registry_config: Mutex::new(None),\n            inner: HttpBackend::new(source_id, gctx, name)?,\n        })\n    }\n\n    fn inner(&self) -> &HttpBackend<'gctx> {\n        &self.inner\n    }\n\n    /// Get the registry configuration from either cache or remote.\n    async fn config(&self) -> CargoResult<RegistryConfig> {\n        let Some(config) = self.config_opt().await? else {\n            return Err(anyhow::anyhow!(\"config.json not found\"));\n        };\n        Ok(config)\n    }\n\n    /// Get the registry configuration from either cache or remote.\n    /// Returns None if the config is not available.\n    async fn config_opt(&self) -> CargoResult<Option<RegistryConfig>> {\n        let mut config = self.registry_config.lock().await;\n        if let Some(config) = &*config\n            && self.inner().is_fresh(RegistryConfig::NAME)\n        {\n            Ok(Some(config.clone()))\n        } else {\n            let result = self.config_opt_inner().await?;\n            *config = result.clone();\n            Ok(result)\n        }\n    }","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/rust-lang/cargo/blob/eb98b54bc9f3c74519f43d066cb3fd02ebc88df0/src/sources/registry/http_remote.rs#L84-L120","documentation":"An HTTP (sparse) registry backend could not obtain `config.json` from the remote, and `config_opt()` returned `None`. The config is mandatory — it declares the registry's tarball URL template, auth requirements, etc. — so Cargo treats its absence as a hard error when `config()` is required.","triggerScenarios":"Sparse/HTTP registry `config_opt()` returns `None` — typically because the HTTP request for `config.json` returned 404, the registry is unreachable, or the cached config could not be loaded and the remote fetch yielded nothing usable. Then code that requires the config calls `config()` which converts `None` into this error.","commonSituations":"Pointing a sparse registry at a URL that does not serve `config.json`; typo'd `registries.<name>.index = \"sparse+https://...\"`; registry server outage / 404; auth required but token missing so config fetch returns empty; trailing-slash mismatch causing a 404 on `<index>/config.json`.","solutions":["Verify the registry URL is correct and ends with `/`: open `<index>/config.json` in a browser.","Ensure auth token is set (`registries.<name>.token` or `CARGO_REGISTRIES_<NAME>_TOKEN`) if the registry requires authentication.","Remove the cached index (`~/.cargo/registry/index/<name>`) and re-run `cargo fetch`.","Confirm the registry server is up and serving the sparse index protocol."],"exampleFix":"# before: missing trailing slash or wrong URL\n[registries.myreg]\nindex = \"sparse+https://myreg.example.com\"\n\n# after\n[registries.myreg]\nindex = \"sparse+https://myreg.example.com/\"\ntoken = \"...\"","handlingStrategy":"validation","validationCode":"async fn ensure_config(backend: &HttpBackend<'_>) -> Result<(), anyhow::Error> {\n    if backend.config_opt().await?.is_none() {\n        anyhow::bail!(\"registry does not serve config.json; check index URL and auth\");\n    }\n    Ok(())\n}","typeGuard":"async fn registry_has_config(backend: &HttpBackend<'_>) -> bool {\n    backend.config_opt().await.ok().flatten().is_some()\n}","tryCatchPattern":"match remote.config().await {\n    Ok(c) => Ok(c),\n    Err(e) if e.to_string().contains(\"config.json not found\") => {\n        // surface URL/auth hint, then abort or prompt for token\n        Err(anyhow!(\"config.json missing at {}; verify `registries.<name>.index` and token\", backend.url))\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Always end sparse registry URLs with `/`.","Verify `<index>/config.json` is reachable in a browser before configuring.","Set auth tokens for private registries.","Clear and refetch the index if the server recovers."],"tags":["cargo","registry","sparse","config","http","configuration"],"backgroundTag":null,"analyzedSha":"eb98b54bc9f3c74519f43d066cb3fd02ebc88df0","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}