rust-lang/cargo · error
path at `{}` was not valid utf-8
Error message
path at `{}` was not valid utf-8 What it means
From paths::read (crates/cargo-util/src/paths.rs:169-174). It reads file bytes via read_bytes then converts to String with String::from_utf8; on failure it bails. Cargo expects UTF-8 for every text file it parses (manifests, config, lockfile, credential tokens), so non-UTF-8 content is treated as a hard error rather than lossy.
Source
Thrown at crates/cargo-util/src/paths.rs:172
.with_context(|| format!("failed to load metadata for path `{}`", path.display()))
}
/// Returns metadata for a file without following symlinks.
///
/// Equivalent to [`std::fs::metadata`] with better error messages.
pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> Result<Metadata> {
let path = path.as_ref();
std::fs::symlink_metadata(path)
.with_context(|| format!("failed to load metadata for path `{}`", path.display()))
}
/// Reads a file to a string.
///
/// Equivalent to [`std::fs::read_to_string`] with better error messages.
pub fn read(path: &Path) -> Result<String> {
match String::from_utf8(read_bytes(path)?) {
Ok(s) => Ok(s),
Err(_) => anyhow::bail!("path at `{}` was not valid utf-8", path.display()),
}
}
/// Reads a file into a bytes vector.
///
/// Equivalent to [`std::fs::read`] with better error messages.
pub fn read_bytes(path: &Path) -> Result<Vec<u8>> {
fs::read(path).with_context(|| format!("failed to read `{}`", path.display()))
}
/// Writes a file to disk.
///
/// Equivalent to [`std::fs::write`] with better error messages.
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> {
let path = path.as_ref();
fs::write(path, contents.as_ref())
.with_context(|| format!("failed to write `{}`", path.display()))
}View on GitHub (pinned to 0e07a15537)
Solutions
- Re-save the offending file as UTF-8 (most editors have an encoding command).
- Identify which file failed from the `{}` path in the message, then inspect its encoding (`file -i <path>`).
- If you genuinely need binary data, the calling code should use paths::read_bytes instead of paths::read.
- Restore the file from version control if it was corrupted.
Example fix
// before (caller expecting text but file is binary)
let text = cargo_util::paths::read(&path)?; // bails on non-utf8
// after (handle binary gracefully)
let bytes = cargo_util::paths::read_bytes(&path)?;
let text = match std::str::from_utf8(&bytes) {
Ok(s) => s.to_owned(),
Err(_) => /* lossy fallback or user error */ String::from_utf8_lossy(&bytes).into_owned(),
}; Defensive patterns
Strategy: validation
Validate before calling
// Validate UTF-8 before assuming text
fn try_read_text(path: &std::path::Path) -> Result<String, std::io::Error> {
let bytes = std::fs::read(path)?;
Ok(std::str::from_utf8(&bytes)
.map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "non-utf8"))?
.to_owned())
}
// or simply use cargo_util::paths::read_bytes when binary is acceptable Type guard
fn is_utf8_file(path: &std::path::Path) -> bool {
std::fs::read(path)
.ok()
.map(|b| std::str::from_utf8(&b).is_ok())
.unwrap_or(false)
} Try / catch
match cargo_util::paths::read(&path) {
Ok(s) => s,
Err(_) => {
let bytes = cargo_util::paths::read_bytes(&path)?;
String::from_utf8_lossy(&bytes).into_owned()
}
} Prevention
- Always save manifests/config as UTF-8.
- In editors, set the default encoding to UTF-8.
- When unsure if a file is text, use read_bytes and validate before converting.
When it happens
Trigger: Cargo reads a file (Cargo.toml, .cargo/config.toml, a registry token cache file, a credential) whose bytes are not valid UTF-8. For example a manifest saved in Latin-1/GBK/Shift-JIS, or a binary file mistakenly placed where text is expected.
Common situations: An editor or legacy toolchain saved Cargo.toml in a non-UTF-8 encoding. A credential file corrupted or overwritten with binary. Git autocrlf or transcoding mishandling on Windows with legacy locales. A path collision where Cargo opens the wrong (binary) file.
Related errors
- failed to parse process output: {}
- Character at line {} is invalid. Cargo only supports UTF-8.
- utf-8 home
- no executable for `{}` found in PATH
- failed to open `{}`: {}
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/307b2c7fb5db7da2.json.
Report an issue: GitHub.