Schniz/fnm · error · anyhow::Error
Can't read PATH env var
Error message
Can't read PATH env var
What it means
PowerShell's `Shell::path` reads the current process PATH with `std::env::var_os("PATH")` so it can prepend fnm's bin dir and re-emit `$env:PATH = ...`. If no PATH variable exists in the environment at all, `var_os` returns None and this anyhow error is produced while running `fnm env --shell power-shell` or `fnm use`.
Source
Thrown at src/shell/powershell.rs:13
use crate::version_file_strategy::VersionFileStrategy;
use super::Shell;
use indoc::formatdoc;
use std::path::Path;
#[derive(Debug)]
pub struct PowerShell;
impl Shell for PowerShell {
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(|source| anyhow::anyhow!("Can't join paths: {source}"))?;
let new_path = new_path
.to_str()
.ok_or_else(|| anyhow::anyhow!("Can't read PATH"))?;
Ok(self.set_env_var("PATH", new_path))
}
fn set_env_var(&self, name: &str, value: &str) -> String {
format!(r#"$env:{name} = "{value}""#)
}
fn use_on_cd(&self, config: &crate::config::FnmConfig) -> anyhow::Result<String> {
let version_file_exists_condition = if config.resolve_engines() {
"(Test-Path .nvmrc) -Or (Test-Path .node-version) -Or (Test-Path package.json)"
} else {View on GitHub (pinned to 86adc9676c)
Solutions
- Restore a PATH before invoking fnm: PowerShell `$env:PATH = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [Environment]::GetEnvironmentVariable('Path','User')`.
- In containers/cron, export a baseline: `PATH=/usr/local/bin:/usr/bin:/bin` (Windows: `set PATH=C:\Windows\System32;C:\Windows`).
- If spawning fnm from code, replace `env_clear()` with selective env removal or re-pass PATH explicitly.
- Update fnm; newer releases may degrade gracefully by emitting only fnm's bin dir.
Example fix
# before (PowerShell, PATH was removed)
Remove-Item Env:PATH
fnm env --shell power-shell # error: Can't read PATH env var
# after
$env:PATH = [Environment]::GetEnvironmentVariable('Path','Machine')
fnm env --shell power-shell # $env:PATH = ... emitted Defensive patterns
Strategy: validation
Validate before calling
// PowerShell: fail fast before calling fnm
if (-not $env:PATH) { throw "PATH is not set; refusing to run fnm env" }
fnm env --shell power-shell Type guard
fn has_path_env() -> bool {
std::env::var_os("PATH").is_some()
} Try / catch
$out = fnm env --shell power-shell 2>&1
if ($LASTEXITCODE -ne 0 -and "$out" -match "Can't read PATH env var") {
$env:PATH = [Environment]::GetEnvironmentVariable('Path','Machine')
$out = fnm env --shell power-shell
} Prevention
- Never spawn fnm from `env -i` or after env_clear() without re-adding PATH.
- In cron/systemd/containers, always define a baseline PATH.
- Add a PATH precheck to wrapper scripts that call fnm.
When it happens
Trigger: `fnm env --shell power-shell` / `fnm use` in a process whose environment has no PATH — spawned via `env -i`, `Command::env_clear()` without re-adding PATH, a stripped CI/cron/scheduled-task environment, or a minimal container.
Common situations: Minimal Docker images invoked with a sanitized env; Windows scheduled tasks or services with no user environment; CI steps that `Remove-Item Env:PATH` or start powershell with `-Command` from a bare service; test harnesses that clear the environment.
Related errors
- Can't read PATH
- Can't read PATH env var
- Can't convert path to string
- Can't convert path to string
- Can't join paths: {source}
AI-assisted analysis of Schniz/fnm@86adc9676c (2026-08-16).
Data as JSON: /api/errors/88bbbe860d521782.
Report an issue: GitHub.