Schniz/fnm · error · anyhow::Error
Can't convert path to string
Error message
Can't convert path to string
What it means
fnm's Fish shell integration builds a `set -gx PATH ...` statement from a `&Path` in `Shell::path`. `Path::to_str()` returns None when the path is not valid UTF-8, and that None becomes this anyhow error. It fires while generating shell setup output such as `fnm env --shell fish`.
Source
Thrown at src/shell/fish.rs:18
use crate::version_file_strategy::VersionFileStrategy;
use super::shell::Shell;
use indoc::formatdoc;
use std::path::Path;
#[derive(Debug)]
pub struct Fish;
impl Shell for Fish {
fn to_clap_shell(&self) -> clap_complete::Shell {
clap_complete::Shell::Fish
}
fn path(&self, path: &Path) -> anyhow::Result<String> {
let path = path
.to_str()
.ok_or_else(|| anyhow::anyhow!("Can't convert path to string"))?;
let path =
super::windows_compat::maybe_fix_windows_path(path).unwrap_or_else(|| path.to_string());
Ok(format!("set -gx PATH {path:?} $PATH;"))
}
fn set_env_var(&self, name: &str, value: &str) -> String {
format!("set -gx {name} {value:?};")
}
fn use_on_cd(&self, config: &crate::config::FnmConfig) -> anyhow::Result<String> {
let version_file_exists_condition = if config.resolve_engines() {
"test -f .node-version -o -f .nvmrc -o -f package.json"
} else {
"test -f .node-version -o -f .nvmrc"
};
let autoload_hook = match config.version_file_strategy() {
VersionFileStrategy::Local => formatdoc!(
r"View on GitHub (pinned to 86adc9676c)
Solutions
- Check each candidate var: `for v in FNM_DIR FNM_MULTISHELL_PATH XDG_RUNTIME_DIR; printf '%s' "$$v" | iconv -f UTF-8 -t UTF-8 >/dev/null || echo "$v invalid"; end`.
- Reset to safe values: `set -Ux FNM_DIR ~/.local/share/fnm` and `set -e FNM_MULTISHELL_PATH`, then restart the shell.
- Ensure LANG/LC_ALL are UTF-8 locales so system tools emit UTF-8 paths.
- Clear stale multishell entries under the fnm multishells storage dir and let fnm recreate them.
Example fix
# before set -Ux FNM_DIR /mnt/data/bad\xffpath fnm env --shell fish # error: Can't convert path to string # after set -e FNM_DIR set -Ux FNM_DIR ~/.local/share/fnm fnm env --shell fish # set -gx PATH ... emitted
Defensive patterns
Strategy: validation
Validate before calling
fn fnm_paths_are_utf8() -> bool {
["FNM_DIR", "FNM_MULTISHELL_PATH", "XDG_RUNTIME_DIR", "XDG_CACHE_HOME"]
.iter()
.filter_map(std::env::var_os)
.all(|v| v.to_str().is_some())
} Type guard
fn is_utf8_path(p: &std::path::Path) -> bool {
p.to_str().is_some()
} Try / catch
match fish_shell.path(&multishell_dir) {
Ok(line) => println!("{line}"),
Err(_) => eprintln!("fnm env failed; reset FNM_DIR/FNM_MULTISHELL_PATH to UTF-8 paths"),
} Prevention
- Set FNM_DIR once from a known-good UTF-8 literal in config.fish.
- Avoid piping env var values through locale-dependent tools before exporting them.
- Periodically prune stale multishell entries so only fnm-created (UTF-8) names exist.
When it happens
Trigger: Running `fnm env --shell fish` (or any command that renders the Fish PATH line) when the multishell path / fnm base dir contains non-UTF-8 bytes — typically via a polluted FNM_MULTISHELL_PATH, FNM_DIR, or the XDG runtime/temp dir they derive from.
Common situations: Fish config files (`config.fish`) saved in a non-UTF-8 encoding setting FNM_DIR; legacy-encoded home or temp directories; XDG_RUNTIME_DIR/XDG_CACHE_HOME containing invalid bytes; multishell dirs left over from a crashed session with mangled names.
Related errors
- Can't convert path to string
- Path is not valid UTF-8
- Can't read PATH
- Can't convert path to string
- Can't read PATH env var
AI-assisted analysis of Schniz/fnm@86adc9676c (2026-08-16).
Data as JSON: /api/errors/a7c18b23a21d2e74.
Report an issue: GitHub.