facebook/flow · error
failed to get executable path
Error message
failed to get executable path
What it means
To compute the client/server build id, flow hashes the bytes of its own executable; `std::env::current_exe().expect("failed to get executable path")` panics when the OS cannot resolve the running binary's path. On Linux this resolves /proc/self/exe, so it fails when /proc is missing/restricted or when the binary file was deleted or replaced after the process started (the symlink then points to a deleted inode).
Source
Thrown at rust_port/crates/flow_common_build_id/src/lib.rs:18
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
use std::sync::OnceLock;
use flow_common_xx as xx;
static BUILD_ID: OnceLock<String> = OnceLock::new();
pub fn get_build_id() -> String {
BUILD_ID
.get_or_init(|| {
let mut state = xx::State::new(0);
let executable = std::env::current_exe().expect("failed to get executable path");
let contents = std::fs::read(&executable).unwrap_or_else(|err| {
panic!(
"failed to read executable at {} for flow build id: {}",
executable.display(),
err
)
});
state.update(&contents);
let hash = format!("{:016x}", state.digest());
hash
})
.clone()
}
View on GitHub (pinned to f88ac94bcf)
Solutions
- Restart the flow client/server after an upgrade so it runs the current binary path.
- Change deploy scripts to install via rename (write new file, `mv` over) instead of overwriting the running binary in place.
- Ensure /proc is mounted and /proc/self/exe is readable inside the container or sandbox.
- As a code fix, fall back to argv[0] or a build-time embedded id when current_exe errors.
Example fix
// before
let executable = std::env::current_exe().expect("failed to get executable path");
// after
let executable = std::env::current_exe().unwrap_or_else(|_| {
std::path::PathBuf::from(std::env::args_os().next().unwrap_or_default())
}); Defensive patterns
Strategy: fallback
Validate before calling
// Cheap pre-check where feasible: the exe path must resolve to an existing file
fn exe_resolvable() -> bool {
std::env::current_exe().map(|p| p.exists()).unwrap_or(false)
} Try / catch
let executable = std::env::current_exe()
.unwrap_or_else(|_| std::path::PathBuf::from(std::env::args_os().next().unwrap_or_default())); Prevention
- Deploy binaries via rename/replace, never overwrite a running binary in place.
- Restart long-lived flow processes after upgrades so current_exe resolves to a live file.
- Ensure /proc is mounted and readable inside containers/sandboxes that run flow.
When it happens
Trigger: The flow binary is overwritten or unlinked while running — in-place `cp` during deploys, a package manager upgrade replacing the binary, cargo rebuilding over a still-running binary; containers/chroots without /proc mounted; seccomp/sandbox policies blocking /proc/self/exe.
Common situations: A long-lived flow daemon surviving an upgrade that removed the old binary (its /proc/PID/exe shows `(deleted)`); deploy scripts that overwrite binaries in place; minimal container images with procfs masked.
Related errors
AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20).
Data as JSON: /api/errors/71a28dca88f4140d.
Report an issue: GitHub.