Schniz/fnm · error · anyhow::Error
Can't join paths: {err}
Error message
Can't join paths: {err} What it means
WindowsCmd's `Shell::path` splits the existing PATH, inserts fnm's bin dir at index 0, and rejoins with `std::env::join_paths`. Rejoining fails when any single entry contains the Windows path separator `;` (or `:` on Unix) inside itself, and the io::Error is wrapped into this anyhow error.
Source
Thrown at src/shell/windows_cmd/mod.rs:19
use super::shell::Shell;
use std::path::Path;
#[derive(Debug)]
pub struct WindowsCmd;
impl Shell for WindowsCmd {
fn to_clap_shell(&self) -> clap_complete::Shell {
// TODO: move to Option
panic!("Shell completion is not supported for Windows Command Prompt. Maybe try using PowerShell for a better experience?");
}
fn path(&self, path: &Path) -> anyhow::Result<String> {
let current_path =
std::env::var_os("path").ok_or_else(|| anyhow::anyhow!("Can't read PATH env var"))?;
let mut split_paths: Vec<_> = std::env::split_paths(¤t_path).collect();
split_paths.insert(0, path.to_path_buf());
let new_path = std::env::join_paths(split_paths)
.map_err(|err| anyhow::anyhow!("Can't join paths: {err}"))?;
let new_path = new_path
.to_str()
.ok_or_else(|| anyhow::anyhow!("Can't convert path to string"))?;
Ok(format!("SET PATH={new_path}"))
}
fn set_env_var(&self, name: &str, value: &str) -> String {
format!("SET {name}={value}")
}
fn use_on_cd(&self, config: &crate::config::FnmConfig) -> anyhow::Result<String> {
let path = config.base_dir_with_default().join("cd.cmd");
create_cd_file_at(&path).map_err(|source| {
anyhow::anyhow!(
"Can't create cd.cmd file for use-on-cd at {}: {}",
path.display(),
source
)View on GitHub (pinned to 86adc9676c)
Solutions
- Print PATH raw (`echo %PATH%` or `reg query "HKCU\Environment" /v Path`) and spot entries that contain an internal `;`.
- Fix the entry: quote it in the registry (System Properties → Environment Variables) or rename the folder without `;`.
- Replace the malformed entry with two properly separated entries.
- Re-run `fnm env --shell cmd`.
Example fix
:: before set PATH=C:\tools\a;b;%PATH% fnm env --shell cmd :: error: Can't join paths :: after set PATH=C:\tools\a;C:\tools\b;%PATH% fnm env --shell cmd :: ok
Defensive patterns
Strategy: validation
Validate before calling
fn path_is_joinable() -> bool {
let sep = if cfg!(windows) { ';' } else { ':' };
std::env::var_os("path")
.map(|p| std::env::split_paths(&p).all(|e| !e.as_os_str().to_string_lossy().contains(sep)))
.unwrap_or(false)
} Try / catch
match cmd_shell.path(&dir) {
Ok(out) => out,
Err(e) if e.to_string().contains("join paths") =>
eprintln!("malformed PATH entry containing ';' — clean it and retry: {e}"),
Err(e) => return Err(e),
} Prevention
- Quote paths with special characters when appending to PATH in batch scripts.
- Rename directories so no PATH element contains ';'.
- Verify PATH shape (`echo %PATH%`) after installer runs.
When it happens
Trigger: `fnm env --shell cmd` when one PATH entry embeds a literal `;` in a directory name — e.g. `set PATH=C:\tools\a;b;%PATH%` without quoting — making the element unencodable in a joined PATH.
Common situations: Batch scripts appending unquoted paths containing semicolons; folders literally named with `;` (legal on NTFS); registry PATH edits that lost quotes around `C:\Program Files`-style entries with extra semicolons; ported Unix scripts leaving `:` entries.
Related errors
- Can't join paths: {source}
- Can't read PATH env var
- Can't convert path to string
- Can't read PATH
- Can't create cd.cmd file for use-on-cd at {}: {}
AI-assisted analysis of Schniz/fnm@86adc9676c (2026-08-16).
Data as JSON: /api/errors/77d202bca49999a6.
Report an issue: GitHub.