libnyanpasu/clash-nyanpasu · error
path is not valid UTF-8: {}
Error message
path is not valid UTF-8: {} What it means
The `to_utf8` helper in `core/actor_v2/local_host.rs` converts a `std::path::PathBuf` into a `Utf8PathBuf` and fails with this error when the path contains bytes that are not valid UTF-8 (possible on Unix where paths are arbitrary bytes). The actor-local host layer requires UTF-8 paths so they can be used in typed/string-based APIs, so non-UTF-8 paths are rejected eagerly with the lossy-decoded path in the message.
Source
Thrown at backend/tauri/src/core/actor_v2/local_host.rs:66
let kind = match core {
ClashCore::ClashPremium => CoreKind::ClashPremium,
ClashCore::ClashRs | ClashCore::ClashRsAlpha => CoreKind::ClashRust,
ClashCore::Mihomo | ClashCore::MihomoAlpha => CoreKind::Mihomo,
ClashCore::Meow => CoreKind::Meow,
};
let binary_path = find_binary(&core_type)?;
Ok(CoreSpec {
kind,
binary_path: to_utf8(binary_path)?,
version: None,
features: vec![],
})
}
fn to_utf8(path: std::path::PathBuf) -> Result<Utf8PathBuf> {
Utf8PathBuf::from_path_buf(path)
.map_err(|path| anyhow::anyhow!("path is not valid UTF-8: {}", path.to_string_lossy()))
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn the_local_host_spawns_under_a_temp_root() {
let root = tempfile::TempDir::new().unwrap();
let paths =
PathResolver::with_base_dirs(root.path().join("config"), root.path().join("data"));
let control = build(&paths).await.unwrap();
let _ = control.status();
assert!(!control.executor_is_closed());
}
View on GitHub (pinned to f7dbce2997)
Solutions
- Rename the offending file/directory so its path is valid UTF-8 (the error message shows the lossy name to find it).
- Set the system locale to a UTF-8 locale (e.g. LANG=en_US.UTF-8) so paths decode correctly.
- Check the configured app/profile data directory (env vars like HOME/XDG dirs) for non-UTF-8 bytes and fix it.
- If you control the caller, validate paths early with `to_str()` and surface a clear configuration error.
Example fix
// before
let host = LocalHost::build(to_utf8(path)?);
// after
let path = to_utf8(path).map_err(|e| {
log::error!("app path must be UTF-8: {e}; move the app or fix the locale");
e
})?;
let host = LocalHost::build(path); Defensive patterns
Strategy: validation
Validate before calling
if path.to_str().is_none() {
anyhow::bail!("path {:?} is not valid UTF-8; move the app or fix the system locale", path);
} Type guard
fn is_utf8_path(path: &std::path::Path) -> bool {
path.to_str().is_some()
} Try / catch
let utf8_path = to_utf8(path)
.with_context(|| format!("configure a UTF-8 app path (got {:?})", path))
.map_err(|e| { log::error!("{e:#}"); e })?; Prevention
- Install the app under an ASCII/UTF-8 path
- Use a UTF-8 system locale (LANG/LC_ALL=en_US.UTF-8) on Linux
- Validate configured data/profile directories for non-UTF-8 bytes at startup
- Avoid deriving app paths from user-controlled non-UTF-8 filenames
When it happens
Trigger: Building or passing a filesystem path to the local-host actor helpers where a directory or filename was created with non-UTF-8 bytes (e.g. locale-mismatched bytes on Linux, files created by tools using non-UTF-8 encodings); any code path calling `to_utf8` with such a PathBuf.
Common situations: App installed under a path with non-UTF-8 bytes; user profiles/config dirs on a system with a legacy locale (LC_ALL=C, ISO-8859-1 filenames); extracted archives with mangled filenames; network mounts exposing raw-byte names.
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
- failed to get app_path
- non-UTF-8 source
- non-UTF-8 destination
- config path is not UTF-8: {}
- runtime path is not UTF-8: {}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/0c9d0843bf32538f.
Report an issue: GitHub.