pkgxdev/pkgx · error · anyhow::Error

Could not get the base name of the installation path

Error message

Could not get the base name of the installation path

What it means

`make_symlink` needs the final path component of the installation directory to create the cellar symlink target. If `installation.path.file_name()` returns `None` — the path is empty, `/`, `..`, or otherwise has no basename — it raises `Could not get the base name of the installation path`. Without a basename no valid symlink target can be constructed.

Solutions

  1. Inspect the resolved cellar path (echo $PKGX_DIR, check Config) and ensure it points at a real subdirectory, not `/` or an empty string
  2. Unset/correct a bogus PKGX_DIR environment variable so the default ~/.pkgx cellar is used
  3. When constructing installations programmatically, pass a path with an actual final component (use `PathBuf::from("...").join(name)`)

Example fix

// before
export PKGX_DIR=/
// after
export PKGX_DIR=$HOME/.pkgx
Defensive patterns

Strategy: validation

Validate before calling

fn cellar_path_valid(p: &std::path::Path) -> bool {
    p.file_name().is_some() && p != std::path::Path::new("/")
}

Type guard

fn has_basename(p: &std::path::Path) -> bool {
    p.file_name().map(|n| !n.is_empty()).unwrap_or(false)
}

Try / catch

match install(&pkg, &config) {
    Err(e) if e.to_string().contains("base name of the installation path") => {
        eprintln!("cellar path is malformed (root/empty?); check PKGX_DIR");
    }
    Err(e) => return Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: Calling `install()`/`symlink` where `installation.path` resolves to the filesystem root, is empty, ends in `..`, or was constructed incorrectly (e.g. cellar path config pointing at `/` or an empty PKGX_DIR-derived path).

Common situations: Setting PKGX_DIR (or the cellar path) to `/` or a malformed value, a config bug producing an empty path, or programmatically constructing an `Installation` with a root/empty path in tests or scripts.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of pkgxdev/pkgx@6de1d7e953 (2026-09-10). Data as JSON: /api/errors/fe33fc9385b0a718. Report an issue: GitHub.

Appendix: source

Thrown at crates/lib/src/install.rs:229

async fn make_symlink(
    shelf: &Path,
    symname: &str,
    installation: &Installation,
) -> Result<(), Box<dyn Error>> {
    let symlink_path = shelf.join(symname);

    if symlink_path.is_symlink() {
        if let Err(err) = fs::remove_file(&symlink_path) {
            if err.kind() != std::io::ErrorKind::NotFound {
                return Err(err.into());
            }
        }
    }

    let target = installation
        .path
        .file_name()
        .ok_or_else(|| anyhow::anyhow!("Could not get the base name of the installation path"))?;

    #[cfg(not(windows))]
    std::os::unix::fs::symlink(target, &symlink_path)?;
    #[cfg(windows)]
    std::os::windows::fs::symlink_dir(target, symlink_path)?;

    Ok(())
}

View on GitHub (pinned to 6de1d7e953)