jdx/mise · error
history cannot represent a non-UTF-8 filename; refusing to c
Error message
history cannot represent a non-UTF-8 filename; refusing to change its bytes
What it means
During the history walk, every captured file path is converted to a Rust str to be keyed into capture roots. If a filename is not valid UTF-8 (raw bytes on disk, e.g. from a non-UTF-8 locale filesystem), the history layer refuses to record it rather than silently corrupting or transcoding its bytes, so it aborts the walk.
Source
Thrown at src/system/history/tracked.rs:381
// a hidden local-only history. Explicit encryption permits key files
// to be tracked without storing their plaintext.
walk.files.retain(|path, (_, policy)| {
if let Some(reason) = capture_exclusion(path, policy) {
walk.omitted.push(PathReason {
path: display_path(path),
reason: reason.into(),
});
false
} else {
true
}
});
walk.entries = set.entries.clone();
let config = normalize(&global_config_dir());
let mut roots: BTreeMap<String, CaptureRoot> = BTreeMap::new();
for (path, (owner, _)) in &walk.files {
if path.to_str().is_none() {
eyre::bail!(
"history cannot represent a non-UTF-8 filename; refusing to change its bytes"
);
}
let (label, base, relative) = if let Ok(relative) = path.strip_prefix(&config) {
("config", config.clone(), relative.to_path_buf())
} else if let Ok(relative) = path.strip_prefix(&home) {
("home", home.clone(), relative.to_path_buf())
} else {
(
"fs",
PathBuf::from(std::path::MAIN_SEPARATOR.to_string()),
path.components()
.filter(|c| matches!(c, Component::Normal(_)))
.collect(),
)
};
let label = walk.entries[*owner]
.variantView on GitHub (pinned to afd2eddd3a)
Solutions
- Find and rename the offending non-UTF-8 filename to a UTF-8 name (e.g. with `convmv --notest -f latin1 -t utf8 -r .` or `find . | LC_ALL=C grep -P '[^\x00-\x7F]'` to locate it).
- Move the non-UTF-8 file outside of the tracked roots (home or the mise config directory) so the walk no longer encounters it.
- Delete the offending file if it is no longer needed.
- If you cannot fix the filename, file an issue to request a skip-with-warning mode instead of a hard abort.
Example fix
// before: file named 'r\e9sum\e9.txt' stored as Latin-1 bytes in a tracked directory // after convmv -f latin1 -t utf8 --notest 'r\e9sum\e9.txt' # now valid UTF-8: 'résumé.txt'
Defensive patterns
Strategy: validation
Validate before calling
// before enabling history tracking over a directory, scan for non-UTF-8 names
use std::path::Path;
fn has_non_utf8_names(root: &Path) -> std::io::Result<bool> {
let mut bad = false;
for entry in walkdir_like(root) {
if entry.path().to_str().is_none() {
bad = true;
eprintln!("non-UTF-8 filename: {:?}", entry.path());
}
}
Ok(bad)
} Type guard
fn is_utf8_path(p: &std::path::Path) -> bool { p.to_str().is_some() } Try / catch
match result {
Err(e) if e.to_string().contains("non-UTF-8 filename") => {
eprintln!("rename non-UTF-8 files under tracked roots before tracking");
}
other => other?,
} Prevention
- Keep filenames ASCII or valid UTF-8, especially in directories you track
- Run `find . | grep -P '[^\x00-\x7F]'` occasionally to spot odd names
- Use convmv when unpacking archives from other encodings
- Avoid legacy-locale tools (tar with raw byte names) writing into your home directory
When it happens
Trigger: Running history tracking (walk, invoked via attempt_locked/live_tree/unsaved_paths) over a directory containing a file or directory whose name is not valid UTF-8, e.g. created by a tool using raw bytes or a legacy encoding.
Common situations: Filenames created on Linux with non-UTF-8 locales (Latin-1 bytes, GBK, etc.), files unpacked from old archives, or paths produced by legacy scripts; user then enables mise history tracking over their home directory and the walk hits the bad name.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- glob pattern is not valid UTF-8: {}
- tracking does not support non-UTF-8 filenames
- rustc output is not a regular file: {}
- failed to create file symlink: {err}
- {other:?}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/e9dd19a6f57649fb.
Report an issue: GitHub.