{"record":{"id":"520a1e12f8d5cbf7","repo":"facebook/flow","slug":"unable-to-determine-executable-path","errorCode":null,"errorMessage":"Unable to determine executable path: {}","messagePattern":"Unable to determine executable path: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust_port/crates/flow_common/src/sys_utils.rs","lineNumber":83,"sourceCode":"/// http://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html\n///\n/// ~/foo -> /home/bob/foo if $HOME = \"/home/bob\"\n/// ~joe/foo -> /home/joe/foo if joe's home is /home/joe\npub fn expanduser(path: &str) -> String {\n    if let Some(rest) = path.strip_prefix(\"~/\") {\n        if let Ok(home) = env::var(\"HOME\") {\n            return format!(\"{}/{}\", home, rest);\n        }\n    }\n    path.to_string()\n}\n\npub fn executable_path() -> &'static Path {\n    static CACHED: OnceLock<PathBuf> = OnceLock::new();\n    CACHED\n        .get_or_init(|| {\n            env::current_exe()\n                .unwrap_or_else(|e| panic!(\"Unable to determine executable path: {}\", e))\n        })\n        .as_path()\n}\n\npub fn mkdir_no_fail(dir: &Path) -> io::Result<()> {\n    with_umask(0, || match std::fs::DirBuilder::new().create(dir) {\n        Ok(()) => Ok(()),\n        Err(e) if e.kind() == io::ErrorKind::AlreadyExists => Ok(()),\n        Err(e) => Err(e),\n    })\n}\n\npub fn is_rosetta() -> bool {\n    static CACHED: OnceLock<bool> = OnceLock::new();\n    *CACHED.get_or_init(|| {\n        #[cfg(target_os = \"macos\")]\n        {\n            match std::process::Command::new(\"sysctl\")","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/facebook/flow/blob/f88ac94bcf6992f5d5a158854d94613ebb92c6e6/rust_port/crates/flow_common/src/sys_utils.rs#L65-L101","documentation":"executable_path() caches std::env::current_exe() in a process-wide OnceLock and panics on failure. current_exe resolves the running binary's path (/proc/self/exe on Linux); it fails when the executable file was deleted or replaced after the process started, when /proc is not mounted or masked, or on platforms where the lookup is unsupported.","triggerScenarios":"The flow binary (or a running daemon started from it) is deleted/overwritten by an upgrade while still running; /proc not mounted in a minimal container; exotic execution environments (some chroots, execve-from-memfd) where the path cannot be recovered.","commonSituations":"npm/yarn/apt upgrading flow underneath a long-lived flow server started from the old inode; hardened containers masking /proc; CI caching that swaps binaries mid-job.","solutions":["Restart the flow process/daemon (flow stop, then rerun) so it starts from the current binary","Reinstall the flow package to restore a missing executable file","In containers, ensure /proc is mounted and not masked","Avoid deleting or replacing a binary while processes started from it are alive"],"exampleFix":"# before\nnpm upgrade flow-bin   # while a flow daemon from the old binary is still running\nflow check             # panics: Unable to determine executable path: ...\n\n# after\nflow stop\nnpm upgrade flow-bin\nflow check","handlingStrategy":"retry","validationCode":"# sanity: /proc mounted and self resolvable on Linux\nls -l /proc/self/exe || echo \"procfs unavailable: fix container mounts\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restart flow processes (flow stop) immediately after upgrading the binary","Do not delete or overwrite a binary while processes started from it run","In containers, keep /proc mounted and unmasked"],"tags":["environment","procfs","upgrade","self-path"],"backgroundTag":"current-exe-unavailable","analyzedSha":"f88ac94bcf6992f5d5a158854d94613ebb92c6e6","analyzedAt":"2026-08-20T10:41:37.992Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}