Kuberwastaken/claurst · error
installed binary path has no parent
Error message
installed binary path has no parent: {} What it means
In create_next_to, Path::parent() on the currently installed binary returned None, which happens only for a root-relative bare path like "/bin" or a bare file name with no directory component. The upgrade routine needs the parent directory to stage the new binary next to the old one.
Solutions
- Install the binary in a normal directory (e.g. ~/.local/bin, /usr/local/bin) so it has a resolvable parent.
- Check where the running binary lives (which claurst; readlink /proc/self/exe) and reinstall there properly.
- Pass an explicit target/install path if the tool supports it.
- Avoid running the binary directly from "/" or via a bare-name mount.
Example fix
// before $ sudo cp claurst / # path with no usable parent for staging // after $ sudo cp claurst /usr/local/bin/claurst
Defensive patterns
Strategy: validation
Validate before calling
// validate the install path before upgrading
let path = std::env::current_exe()?;
if path.parent().is_none() {
bail!("binary must be installed in a real directory, not {}", path.display());
} Prevention
- Install binaries into standard bin directories (~/.local/bin, /usr/local/bin)
- Never run an upgradable binary from the filesystem root
- Canonicalize the exe path early so odd layouts surface as clear errors
When it happens
Trigger: current_exe() or the configured binary path resolves to a path with no parent component (e.g. "/" child without intermediate dirs, or a bare relative name when current_dir metadata is odd), in create_next_to during upgrade.
Common situations: Binary copied/moved to an exotic location like filesystem root; running a binary whose path was canonicalized to "/"; custom PATH entry pointing at a bare name; sandboxed environments reporting odd exe paths.
Related errors
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/0db1eabdd1f9bfeb.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/cli/src/upgrade.rs:314
#[cfg(unix)]
struct StagedBinary {
path: PathBuf,
}
#[cfg(unix)]
impl StagedBinary {
fn create_next_to(current: &Path) -> Result<(Self, std::fs::File)> {
use std::ffi::OsString;
use std::fs::OpenOptions;
use std::io::ErrorKind;
use std::sync::atomic::{AtomicU64, Ordering};
static NEXT_STAGE_ID: AtomicU64 = AtomicU64::new(0);
const MAX_ATTEMPTS: usize = 128;
let parent = current
.parent()
.ok_or_else(|| anyhow!("installed binary path has no parent: {}", current.display()))?;
let file_name = current.file_name().ok_or_else(|| {
anyhow!(
"installed binary path has no file name: {}",
current.display()
)
})?;
for _ in 0..MAX_ATTEMPTS {
let id = NEXT_STAGE_ID.fetch_add(1, Ordering::Relaxed);
let mut staged_name = OsString::from(".");
staged_name.push(file_name);
staged_name.push(format!(".upgrade-{}-{}", std::process::id(), id));
let path = parent.join(staged_name);
match OpenOptions::new().write(true).create_new(true).open(&path) {
Ok(file) => return Ok((Self { path }, file)),
Err(error) if error.kind() == ErrorKind::AlreadyExists => continue,
Err(error) => {View on GitHub (pinned to b0637c97ec)