jdx/mise · error
tracking does not support non-UTF-8 filenames
Error message
tracking does not support non-UTF-8 filenames
What it means
When tracking (enrolling) dotfiles into the history system, mise validates that the path can be represented as UTF-8 because paths are stored in config/aliases that require valid UTF-8. Non-UTF-8 filenames (raw bytes, legacy encodings) are rejected up front.
Source
Thrown at src/system/history/tracked.rs:795
pub(crate) fn tree_path_to_display(tree_path: &str) -> String {
let (stem, rest) = tree_path.split_once('/').unwrap_or((tree_path, ""));
let root = stem.split('@').next().unwrap_or(stem);
if root == "config" {
display_path(global_config_dir().join(rest))
} else if root == "home" {
format!("~/{rest}")
} else if let Some(rest) = tree_path.strip_prefix("fs/") {
format!("/{rest}")
} else {
tree_path.to_string()
}
}
/// Root aliases are portable through the home/config mapping. Aliases below
/// those roots are not: canonicalizing them would silently change the enrolled
/// destination on another machine. The leaf itself may still be a symlink.
pub(crate) fn ensure_portable_ancestors(path: &Path) -> Result<()> {
eyre::ensure!(
path.to_str().is_some(),
"tracking does not support non-UTF-8 filenames"
);
let roots = super::sync::layout::Roots::current();
let bases = [
dirs::HOME.to_path_buf(),
global_config_dir(),
roots.home,
roots.config_dir,
];
let relative = |base: &Path| {
let mut components = path.components();
for expected in base.components() {
let actual = components.next()?;
if actual != expected
&& !(cfg!(windows)
&& actual
.as_os_str()View on GitHub (pinned to afd2eddd3a)
Solutions
- Rename the offending file/dir to a valid UTF-8 name (e.g. with convmv)
- Check your locale: use a UTF-8 locale (LANG=en_US.UTF-8) so new files are UTF-8
- Exclude the non-UTF-8 path from tracking rather than enrolling its ancestors
Example fix
// before mise track ./files/ # contains byte-0xFF filename // after convmv -f latin1 -t utf-8 -r ./files/ mise track ./files/
Defensive patterns
Strategy: validation
Validate before calling
if path.to_str().is_none() { eprintln!("skipping non-UTF-8 path: {}", path.display()); } Type guard
fn is_utf8_path(p: &Path) -> bool { p.to_str().is_some() } Try / catch
match Err(m) if m.contains("non-UTF-8 filenames") => { /* rename or skip the path */ } Prevention
- Use a UTF-8 locale on Linux/macOS
- Fix non-UTF-8 filenames with convmv before enrolling dotfiles
- List files with invalid encoding before tracking: find . | grep -P '[^\x00-\x7F]'
When it happens
Trigger: Calling add_requests -> ensure_portable_ancestors with a Path containing invalid UTF-8 bytes (e.g. filenames created under a non-UTF-8 locale or random binary names).
Common situations: On Linux with a non-UTF-8 locale (LC_ALL=C), files created with odd byte sequences; files copied from archives or Windows with legacy encodings; accidentally enrolling a directory containing such files.
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
- history cannot represent a non-UTF-8 filename; refusing to c
- glob pattern is not valid UTF-8: {}
- failed rename: {} -> {}: {err}
- {err} dotfiles: rollback failed: {rollback_err}
- {}
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/15db8e49176feb93.
Report an issue: GitHub.