apache/beam · error · RuntimeError
Executable not found
Error message
Executable {} not found What it means
processes.call wraps subprocess.call and converts OSError (typically FileNotFoundError from exec) into a RuntimeError naming the executable. It exists so Beam pipeline code gets a clearer error than a raw OSError when a required binary is missing.
Solutions
- Check `shutil.which('binary')` returns a path; install the missing executable (e.g. pip/apt install)
- Pass an absolute path to the executable if it lives outside PATH
- Fix PATH in the runtime environment (container image, cron, subprocess env)
- Check file permissions (chmod +x) if the binary exists but is not executable
Example fix
// before
processes.call('gsutil cp a b') # gsutil not installed
// after
if not shutil.which('gsutil'):
install_or_fail('gsutil')
processes.call('gsutil', 'cp', 'a', 'b') Defensive patterns
Strategy: validation
Validate before calling
import shutil
if shutil.which('my-tool') is None:
raise RuntimeError("Executable 'my-tool' not found; install it first") Type guard
def executable_available(name: str) -> bool:
return shutil.which(name) is not None Try / catch
try:
rc = processes.call('my-tool', 'arg')
except RuntimeError as e:
if 'not found' in str(e):
install_tool_or_fallback()
else:
raise Prevention
- Always verify binaries with shutil.which before invoking
- Use absolute paths for executables in production code
- Pin required CLI tools in your container image
- Keep PATH explicit in scheduled/CI environments
When it happens
Trigger: Calling apache_beam.utils.processes.call('some-binary', ...) where the executable is not on PATH or the given path does not exist; any OSError from the subprocess (permission denied, ENOEXEC) also lands here.
Common situations: SDK workers (Dataflow containers) lacking the binary; typo'd executable name; not passing the full path; missing virtualenv activation in scripts.
Related errors
- Could not generate external transform wrappers due to error
- Could not generate protos due to error
- Full trace: \n Output of the failed child process
- Full trace: , \n output of the failed child process
- Full trace: \n Output of the failed child process
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/7df92c5b34978739.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/utils/processes.py:53
PIPE = subprocess.PIPE
STDOUT = subprocess.STDOUT
CalledProcessError = subprocess.CalledProcessError
if TYPE_CHECKING:
call = subprocess.call
check_call = subprocess.check_call
check_output = subprocess.check_output
Popen = subprocess.Popen
else:
def call(*args, **kwargs):
if force_shell:
kwargs['shell'] = True
try:
out = subprocess.call(*args, **kwargs)
except OSError as e:
raise RuntimeError("Executable {} not found".format(args[0])) from e
except subprocess.CalledProcessError as error:
if isinstance(args, tuple) and (args[0][2] == "pip"):
raise RuntimeError( \
"Full traceback: {}\n Pip install failed for package: {} \
\n Output from execution of subprocess: {}" \
.format(traceback.format_exc(), args[0][6], error. output)) from error
else:
raise RuntimeError("Full trace: {}\
\n Output of the failed child process: {} " \
.format(traceback.format_exc(), error.output)) from error
return out
def check_call(*args, **kwargs):
if force_shell:
kwargs['shell'] = True
try:
out = subprocess.check_call(*args, **kwargs)
except OSError as e:View on GitHub (pinned to 12126d8942)