{"record":{"id":"d5eb8f3c375c3025","repo":"Schniz/fnm","slug":"can-t-join-paths-source","errorCode":null,"errorMessage":"Can't join paths: {source}","messagePattern":"Can't join paths: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/shell/powershell.rs","lineNumber":17,"sourceCode":"use crate::version_file_strategy::VersionFileStrategy;\n\nuse super::Shell;\nuse indoc::formatdoc;\nuse std::path::Path;\n\n#[derive(Debug)]\npub struct PowerShell;\n\nimpl Shell for PowerShell {\n    fn path(&self, path: &Path) -> anyhow::Result<String> {\n        let current_path =\n            std::env::var_os(\"PATH\").ok_or_else(|| anyhow::anyhow!(\"Can't read PATH env var\"))?;\n        let mut split_paths: Vec<_> = std::env::split_paths(&current_path).collect();\n        split_paths.insert(0, path.to_path_buf());\n        let new_path = std::env::join_paths(split_paths)\n            .map_err(|source| anyhow::anyhow!(\"Can't join paths: {source}\"))?;\n        let new_path = new_path\n            .to_str()\n            .ok_or_else(|| anyhow::anyhow!(\"Can't read PATH\"))?;\n        Ok(self.set_env_var(\"PATH\", new_path))\n    }\n\n    fn set_env_var(&self, name: &str, value: &str) -> String {\n        format!(r#\"$env:{name} = \"{value}\"\"#)\n    }\n\n    fn use_on_cd(&self, config: &crate::config::FnmConfig) -> anyhow::Result<String> {\n        let version_file_exists_condition = if config.resolve_engines() {\n            \"(Test-Path .nvmrc) -Or (Test-Path .node-version) -Or (Test-Path package.json)\"\n        } else {\n            \"(Test-Path .nvmrc) -Or (Test-Path .node-version)\"\n        };\n        let autoload_hook = match config.version_file_strategy() {\n            VersionFileStrategy::Local => formatdoc!(","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/Schniz/fnm/blob/86adc9676ceb2a509b21e75e74048b93c89f097d/src/shell/powershell.rs#L1-L35","documentation":"After splitting the existing PATH and inserting fnm's bin dir at the front, `Shell::path` for PowerShell rebuilds one PATH string with `std::env::join_paths`. That function fails when any single entry contains the platform's path separator character itself (`;` on Windows, `:` on Unix), because the separator cannot appear unescaped inside an element. The io::Error is wrapped into this anyhow error.","triggerScenarios":"`fnm env --shell power-shell` when the current PATH contains one malformed entry embedding `;` inside a directory name (e.g. `C:\\tools\\a;b` set without quoting), or on Unix an entry containing `:`.","commonSituations":"Windows installers appending unquoted paths with semicolons in folder names; hand-edited system PATH in the registry dropping quotes; WSL interop appending Windows paths into $PATH; scripts doing `$env:PATH += 'C:\\a;b'`.","solutions":["Locate the offending entry: `($env:PATH -split ';') | Where-Object { $_ -match '\\\\|/' -and (Test-Path $_) -eq $false }` — inspect entries that look like two paths glued by `;`.","Rebuild a clean PATH excluding the malformed element, or rename the folder so it has no `;`.","On Unix check for `:` inside PATH entries: `echo \"$PATH\" | tr ':' '\\n' | grep ':'` (anything surviving the split embeds a colon).","Re-run `fnm env --shell power-shell` after fixing PATH."],"exampleFix":"# before\n$env:PATH = 'C:\\tools\\a;b'; + $env:PATH   # one entry containing ';'\nfnm env --shell power-shell   # error: Can't join paths\n\n# after\n$env:PATH = 'C:\\tools\\a;C:\\tools\\b' + ';' + $env:PATH\nfnm env --shell power-shell   # ok","handlingStrategy":"validation","validationCode":"fn path_is_joinable() -> bool {\n    let sep = if cfg!(windows) { ';' } else { ':' };\n    std::env::var_os(\"PATH\")\n        .map(|p| {\n            std::env::split_paths(&p)\n                .all(|entry| !entry.as_os_str().to_string_lossy().contains(sep))\n        })\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match powershell.path(&dir) {\n    Ok(out) => out,\n    Err(e) if e.to_string().contains(\"join paths\") =>\n        panic!(\"a PATH entry embeds the path separator; clean $env:PATH first: {e}\"),\n    Err(e) => return Err(e),\n}","preventionTips":["Quote every PATH entry you append that may contain ';'.","Prefer two well-separated entries over one entry with an internal separator.","Audit PATH after running third-party installers."],"tags":["rust","powershell","path","path-separator","windows","join-paths"],"backgroundTag":"invalid-path-separator","analyzedSha":"86adc9676ceb2a509b21e75e74048b93c89f097d","analyzedAt":"2026-08-16T21:43:05.725Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}