rust-lang/cargo · error · anyhow::Error
Character at line {} is invalid. Cargo only supports UTF-8.
Error message
Character at line {} is invalid. Cargo only supports UTF-8. What it means
While merging Cargo's ignore entries into an existing .gitignore/.hgignore/.ignore during `cargo new`/`cargo init`, IgnoreList::format_existing reads the file line-by-line as UTF-8. If a byte sequence is not valid UTF-8, the BufRead returns ErrorKind::InvalidData and Cargo surfaces this message naming the offending line number. Cargo only writes/manages UTF-8 ignore files.
Source
Thrown at src/ops/cargo_new.rs:660
VersionControl::Fossil => &self.fossil_ignore,
_ => &self.ignore,
};
ignore_items.join("\n") + "\n"
}
/// `format_existing` is used to format the `IgnoreList` when the ignore file
/// already exists. It reads the contents of the given `BufRead` and
/// checks if the contents of the ignore list are already existing in the
/// file.
fn format_existing<T: BufRead>(&self, existing: T, vcs: VersionControl) -> CargoResult<String> {
let mut existing_items = Vec::new();
for (i, item) in existing.lines().enumerate() {
match item {
Ok(s) => existing_items.push(s),
Err(err) => match err.kind() {
ErrorKind::InvalidData => {
return Err(anyhow!(
"Character at line {} is invalid. Cargo only supports UTF-8.",
i
));
}
_ => return Err(anyhow!(err)),
},
}
}
let ignore_items = match vcs {
VersionControl::Hg => &self.hg_ignore,
VersionControl::Fossil => &self.fossil_ignore,
_ => &self.ignore,
};
let mut out = String::new();
// Fossil does not support `#` comments.View on GitHub (pinned to 0e07a15537)
Solutions
- Re-encode the offending ignore file to UTF-8: `iconv -f LATIN1 -t UTF-8 .gitignore -o .gitignore`
- Open the file in an editor, fix or remove the invalid characters, and save as UTF-8
- Delete the ignore file and let Cargo regenerate it from scratch
Example fix
# before: .gitignore contains non-UTF-8 bytes -> error # after iconv -f LATIN1 -t UTF-8 .gitignore -o .gitignore.utf8 && mv .gitignore.utf8 .gitignore cargo init
Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn ensure_ignore_utf8(path: &Path) -> Result<(), String> {
let bytes = std::fs::read(path).map_err(|e| e.to_string())?;
std::str::from_utf8(&bytes).map(|_| ()).map_err(|_| format!("{} is not valid UTF-8", path.display()))
}
for f in [".gitignore", ".hgignore", ".ignore"] { ensure_ignore_utf8(Path::new(f))?; } Type guard
import { readFileSync } from 'fs';
function isValidUtf8(path: string): boolean {
try { new TextDecoder('utf-8', { fatal: true }).decode(readFileSync(path)); return true; }
catch { return false; }
} Prevention
- Configure editors/git to write .gitignore as UTF-8 without BOM
- Audit ignore files for non-ASCII bytes before running cargo init
- Add a pre-commit hook rejecting non-UTF-8 ignore files
When it happens
Trigger: `cargo init` (or `cargo new` into a dir) where the existing `.gitignore`/`.hgignore`/`.ignore` contains non-UTF-8 bytes - e.g. Latin-1 accented characters, a stray binary blob, or a file written by a tool that used the system codepage.
Common situations: Checkouts on Windows where the editor saved .gitignore as UTF-16 or with BOM+CRLF corruption; copy-pasted ignore content from a non-UTF-8 source; files touched by a misbehaving sed/iconv; legacy repos with mojibake.
Related errors
- path at `{}` was not valid utf-8
- {err}
- utf-8 home
- unknown vcs specification: `{}`
- more than one of .hg, .git, .pijul, .fossil configurations f
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/298f41657629dfcf.json.
Report an issue: GitHub.