Schniz/fnm · error · anyhow::Error
Can't convert path to string
Error message
Can't convert path to string
What it means
fnm's Bash shell integration builds an `export PATH=...` line from a `&Path` (the multishell symlink directory) in `Shell::path`. It calls `Path::to_str()`, which returns None when the path holds bytes that are not valid UTF-8, and converts that None into an anyhow error with this message. It surfaces from commands that emit shell setup, primarily `fnm env --shell bash` and `fnm use`.
Source
Thrown at src/shell/bash.rs:18
use crate::version_file_strategy::VersionFileStrategy;
use super::shell::Shell;
use indoc::formatdoc;
use std::path::Path;
#[derive(Debug)]
pub struct Bash;
impl Shell for Bash {
fn to_clap_shell(&self) -> clap_complete::Shell {
clap_complete::Shell::Bash
}
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!("export PATH={path:?}:\"$PATH\""))
}
fn set_env_var(&self, name: &str, value: &str) -> String {
format!("export {name}={value:?}")
}
fn use_on_cd(&self, config: &crate::config::FnmConfig) -> anyhow::Result<String> {
let version_file_exists_condition = if config.resolve_engines() {
"-f .node-version || -f .nvmrc || -f package.json"
} else {
"-f .node-version || -f .nvmrc"
};
let autoload_hook = match config.version_file_strategy() {
VersionFileStrategy::Local => formatdoc!(
r"View on GitHub (pinned to 86adc9676c)
Solutions
- Verify the suspect env var is valid UTF-8: `printf '%s' "$FNM_DIR" | iconv -f UTF-8 -t UTF-8 >/dev/null || echo invalid` (repeat for FNM_MULTISHELL_PATH and TMPDIR).
- Point FNM_DIR at a clean ASCII/UTF-8 path: `export FNM_DIR="$HOME/.fnm"` and unset the broken FNM_MULTISHELL_PATH.
- Fix the locale (LANG/LC_ALL=en_US.UTF-8) so dependent tools stop producing non-UTF-8 names, then recreate the multishell dir by opening a new shell.
- If a username/home dir itself is non-UTF-8, relocate fnm storage with `--fnm-dir` to an ASCII path.
Example fix
# before export FNM_DIR=$'/tmp/bad\xffdir' fnm env --shell bash # error: Can't convert path to string # after unset FNM_DIR export FNM_DIR="$HOME/.local/share/fnm" fnm env --shell bash # export PATH=... emitted
Defensive patterns
Strategy: validation
Validate before calling
fn fnm_paths_are_utf8() -> bool {
["FNM_DIR", "FNM_MULTISHELL_PATH", "TMPDIR"]
.iter()
.filter_map(std::env::var_os)
.all(|v| v.to_str().is_some())
}
// run before invoking `fnm env --shell bash`; abort with a clear message if false Type guard
fn is_utf8_path(p: &std::path::Path) -> bool {
p.to_str().is_some()
} Try / catch
match bash_shell.path(&multishell_dir) {
Ok(line) => println!("{line}"),
Err(e) if e.to_string().contains("convert path to string") =>
eprintln!("fnm dir is not valid UTF-8; check FNM_DIR / FNM_MULTISHELL_PATH"),
Err(e) => return Err(e),
} Prevention
- Keep FNM_DIR, FNM_MULTISHELL_PATH and temp dirs on ASCII-named paths.
- Save shell rc files that export fnm variables as UTF-8.
- Validate env-derived paths with iconv (or Path::to_str) in bootstrap scripts before calling fnm.
When it happens
Trigger: Running `fnm env --shell bash` (or any flow that renders the Bash PATH export) when the path involved — FNM_MULTISHELL_PATH, FNM_DIR, or the temp/multishell storage dir derived from them — contains invalid UTF-8 bytes.
Common situations: FNM_DIR or FNM_MULTISHELL_PATH exported from a script saved in a legacy code page; a Unix username or /tmp path with non-UTF-8 bytes (e.g. Latin-1 or Shift-JIS filenames); paths mangled by backup/restore tools; env vars set with raw bytes via `export FNM_DIR=$'\xff...'`.
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/234eff3c032c6a48.
Report an issue: GitHub.