{"record":{"id":"4cc30187eb119b63","repo":"Kuberwastaken/claurst","slug":"installed-binary-path-has-no-file-name","errorCode":null,"errorMessage":"installed binary path has no file name: {}","messagePattern":"installed binary path has no file name: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-rust/crates/cli/src/upgrade.rs","lineNumber":316,"sourceCode":"    path: PathBuf,\n}\n\n#[cfg(unix)]\nimpl StagedBinary {\n    fn create_next_to(current: &Path) -> Result<(Self, std::fs::File)> {\n        use std::ffi::OsString;\n        use std::fs::OpenOptions;\n        use std::io::ErrorKind;\n        use std::sync::atomic::{AtomicU64, Ordering};\n\n        static NEXT_STAGE_ID: AtomicU64 = AtomicU64::new(0);\n        const MAX_ATTEMPTS: usize = 128;\n\n        let parent = current\n            .parent()\n            .ok_or_else(|| anyhow!(\"installed binary path has no parent: {}\", current.display()))?;\n        let file_name = current.file_name().ok_or_else(|| {\n            anyhow!(\n                \"installed binary path has no file name: {}\",\n                current.display()\n            )\n        })?;\n\n        for _ in 0..MAX_ATTEMPTS {\n            let id = NEXT_STAGE_ID.fetch_add(1, Ordering::Relaxed);\n            let mut staged_name = OsString::from(\".\");\n            staged_name.push(file_name);\n            staged_name.push(format!(\".upgrade-{}-{}\", std::process::id(), id));\n            let path = parent.join(staged_name);\n\n            match OpenOptions::new().write(true).create_new(true).open(&path) {\n                Ok(file) => return Ok((Self { path }, file)),\n                Err(error) if error.kind() == ErrorKind::AlreadyExists => continue,\n                Err(error) => {\n                    return Err(error).with_context(|| {\n                        format!(","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/Kuberwastaken/claurst/blob/b0637c97ec34144387cbf2f74f65df6d16a6cef1/src-rust/crates/cli/src/upgrade.rs#L298-L334","documentation":"create_next_to called Path::file_name() on the installed binary path and got None, meaning the path terminates in '..' or is the filesystem root. The upgrader needs the original file name to name the staged replacement binary. This is essentially an invariant violation: an executable path should always have a final component.","triggerScenarios":"The resolved current-exe path ends with '..' or is root ('/'), so file_name() returns None in create_next_to during run_upgrade's staging step.","commonSituations":"Symlink chains or canonicalization producing a trailing '..' component; binary path set to '/' via misconfiguration; exotic container/sandbox mount layouts; manually hacked install location.","solutions":["Canonicalize the binary path before staging so '..' components are resolved away.","Reinstall the binary at a normal absolute path with a real file name.","Inspect how the binary is being launched (wrapper scripts, symlinks) and fix the path.","Fall back to installing to a default bin directory if the current path is unusable."],"exampleFix":"// before\nlet current = std::env::current_exe()?;\n// after\nlet current = std::env::current_exe()?.canonicalize()?;","handlingStrategy":"validation","validationCode":"// canonicalize to eliminate '..' and root-only paths\nlet current = std::env::current_exe()?.canonicalize()?;\nif current.file_name().is_none() {\n    bail!(\"cannot determine binary file name from {}\", current.display());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always canonicalize current_exe before path decomposition","Avoid symlink chains ending in '..' components for the install path","Reinstall via the official installer so the path has a real final component"],"tags":["filesystem","path","upgrade","self-update"],"backgroundTag":"internal-invariant-violation","analyzedSha":"b0637c97ec34144387cbf2f74f65df6d16a6cef1","analyzedAt":"2026-09-10T00:24:58.650Z","contentChangedAt":"2026-09-10T00:24:58.650Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}