{"record":{"id":"7df92c5b34978739","repo":"apache/beam","slug":"executable-not-found","errorCode":null,"errorMessage":"Executable {} not found","messagePattern":"Executable (.+?) not found","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/utils/processes.py","lineNumber":53,"sourceCode":"PIPE = subprocess.PIPE\nSTDOUT = subprocess.STDOUT\nCalledProcessError = subprocess.CalledProcessError\n\nif TYPE_CHECKING:\n  call = subprocess.call\n  check_call = subprocess.check_call\n  check_output = subprocess.check_output\n  Popen = subprocess.Popen\n\nelse:\n\n  def call(*args, **kwargs):\n    if force_shell:\n      kwargs['shell'] = True\n    try:\n      out = subprocess.call(*args, **kwargs)\n    except OSError as e:\n      raise RuntimeError(\"Executable {} not found\".format(args[0])) from e\n    except subprocess.CalledProcessError as error:\n      if isinstance(args, tuple) and (args[0][2] == \"pip\"):\n        raise RuntimeError( \\\n          \"Full traceback: {}\\n Pip install failed for package: {} \\\n          \\n Output from execution of subprocess: {}\" \\\n          .format(traceback.format_exc(), args[0][6], error. output)) from error\n      else:\n        raise RuntimeError(\"Full trace: {}\\\n           \\n Output of the failed child process: {} \" \\\n          .format(traceback.format_exc(), error.output)) from error\n    return out\n\n  def check_call(*args, **kwargs):\n    if force_shell:\n      kwargs['shell'] = True\n    try:\n      out = subprocess.check_call(*args, **kwargs)\n    except OSError as e:","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/utils/processes.py#L35-L71","documentation":"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.","triggerScenarios":"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.","commonSituations":"SDK workers (Dataflow containers) lacking the binary; typo'd executable name; not passing the full path; missing virtualenv activation in scripts.","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"],"exampleFix":"// before\nprocesses.call('gsutil cp a b')  # gsutil not installed\n// after\nif not shutil.which('gsutil'):\n    install_or_fail('gsutil')\nprocesses.call('gsutil', 'cp', 'a', 'b')","handlingStrategy":"validation","validationCode":"import shutil\nif shutil.which('my-tool') is None:\n    raise RuntimeError(\"Executable 'my-tool' not found; install it first\")","typeGuard":"def executable_available(name: str) -> bool:\n    return shutil.which(name) is not None","tryCatchPattern":"try:\n    rc = processes.call('my-tool', 'arg')\nexcept RuntimeError as e:\n    if 'not found' in str(e):\n        install_tool_or_fallback()\n    else:\n        raise","preventionTips":["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"],"tags":["python","subprocess","command-not-found"],"backgroundTag":"command-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}