{"record":{"id":"ac6c35ce6e271471","repo":"rust-lang/cargo","slug":"non-utf8-path","errorCode":null,"errorMessage":"non UTF8 path: {}","messagePattern":"non UTF8 path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/registry/http_remote.rs","lineNumber":283,"sourceCode":"    }\n\n    async fn load(\n        &self,\n        _root: &Path,\n        path: &Path,\n        index_version: Option<&str>,\n    ) -> CargoResult<LoadResponse> {\n        // Ensure the config is loaded.\n        let Some(config) = self.config_opt().await? else {\n            return Ok(LoadResponse::NotFound);\n        };\n        self.inner()\n            .auth_required\n            .update(|v| v || config.auth_required);\n\n        let path = path\n            .to_str()\n            .ok_or_else(|| anyhow::anyhow!(\"non UTF8 path: {}\", path.display()))?;\n        self.sparse_fetch(path, index_version).await\n    }\n\n    async fn config(&self) -> CargoResult<Option<RegistryConfig>> {\n        Ok(Some(self.config().await?))\n    }\n\n    fn invalidate_cache(&self) {\n        // Actually updating the index is more or less a no-op for this implementation.\n        // All it does is ensure that a subsequent load will double-check files with the\n        // server rather than rely on a locally cached copy of the index files.\n        debug!(\"invalidated index cache\");\n        self.inner().fresh.borrow_mut().clear();\n        self.inner().requested_update.set(true);\n    }\n\n    fn set_quiet(&mut self, quiet: bool) {\n        self.inner().quiet.set(quiet);","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/rust-lang/cargo/blob/eb98b54bc9f3c74519f43d066cb3fd02ebc88df0/src/sources/registry/http_remote.rs#L265-L301","documentation":"While loading a crate's metadata from a sparse (HTTP) registry, Cargo converts the requested `path` to a `&str` via `Path::to_str()`. If the path contains non-UTF-8 bytes (OsStr not representable as UTF-8), conversion fails. Crate names in the index are always ASCII, so this indicates a malformed or non-UTF-8 path was passed to the load routine.","triggerScenarios":"`load()` is called with a `&Path` whose OsStr is not valid UTF-8; `.to_str()` returns `None`. Practically unreachable from normal Cargo flows (crate names are validated ASCII) but could be hit by programmatic callers passing arbitrary paths or on platforms with non-UTF-8 path encoding.","commonSituations":"Programmatic use of Cargo as a library passing non-UTF-8 paths; filesystem locale producing non-UTF-8 path bytes; corrupted in-memory path construction.","solutions":["Ensure any path passed to registry load routines is valid UTF-8 (sanitize/normalize crate names before lookup).","If calling Cargo as a library, validate `path.to_str().is_some()` before invoking load.","Report a Cargo bug if this fires during normal CLI usage (crate names should be ASCII)."],"exampleFix":"// before: pass arbitrary OsStr path\nlet resp = backend.load(root, non_utf8_path, None).await?;\n\n// after: validate UTF-8 first\nlet path_str = path.to_str()\n    .ok_or_else(|| anyhow!(\"non UTF8 path\"))?;\nlet resp = backend.load(root, std::path::Path::new(path_str), None).await?;","handlingStrategy":"type-guard","validationCode":"fn require_utf8_path(path: &Path) -> Result<&str, anyhow::Error> {\n    path.to_str().ok_or_else(|| anyhow::anyhow!(\"path is not UTF-8: {}\", path.display()))\n}","typeGuard":"fn is_utf8_path(path: &std::path::Path) -> bool { path.to_str().is_some() }","tryCatchPattern":"let path_str = match path.to_str() {\n    Some(s) => s,\n    None => { tracing::warn!(\"skipping non-UTF-8 path\"); return Ok(LoadResponse::NotFound); }\n};","preventionTips":["Sanitize crate names to ASCII before lookup.","When calling Cargo as a library, never pass arbitrary OsStr paths.","Report a bug if this surfaces during normal CLI usage."],"tags":["cargo","registry","sparse","utf8","path","validation"],"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"}