apache/beam · error · RuntimeError
Worker subprocess exited with return code
Error message
Worker subprocess exited with return code %s
What it means
The WorkerHandler used by the embedded local runner launches the SDK harness as a shell subprocess and blocks on p.wait(). If the process exits with a nonzero return code, the runner raises RuntimeError reporting that code, since the worker died abnormally instead of completing its work.
Solutions
- Check the logging server output above the error for the harness's actual traceback.
- Install missing dependencies in the worker environment (or bundle with --worker_options / requirements).
- Fix user code that raises at import/Deserialization time on the worker (use cloudpickle-compatible, importable code).
- Investigate return codes: 137/-9 indicates OOM — increase memory or reduce parallelism.
Defensive patterns
Strategy: try-catch
Validate before calling
env_ok = all(dep_importable(d) for d in required_deps)
Try / catch
try:
handler.run(worker_command)
except RuntimeError as e:
rc = int(str(e).rsplit(' ', 1)[-1])
if abs(rc) in (9, 137): investigate_oom()
else: inspect_harness_logs() Prevention
- Ensure worker env has all pipeline dependencies
- Watch for return codes 137/-9 (OOM)
- Keep worker python version compatible with the pipeline
- Test pickled DoFns import cleanly on workers
When it happens
Trigger: The SDK harness subprocess started by run() crashes: unhandled exception in user code at harness startup, import errors, OOM kill (return code -9/137), or bad worker command line/environment.
Common situations: Missing dependencies in the worker environment; container/OS OOM killer terminating the harness; python version mismatch; failing --worker_command_line overrides; exceptions during pipeline deserialization (pickled DoFn unavailable on worker).
Related errors
- All workers communicate through gRPC should have worker_id…
- A dataSourceConfiguration or dataSourceProviderFn has…
- A list of URNs for overriding transforms was provided but…
- A cannot be expanded
- A transform cannot be initiated using the provided config…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ebe78607ec94089e.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/runners/portability/local_job_service.py:224
endpoints_pb2.ApiServiceDescriptor(url=self._control_address))
pipeline_options = json_format.MessageToJson(
self._provision_info.provision_info.pipeline_options)
env_dict = dict(
os.environ,
CONTROL_API_SERVICE_DESCRIPTOR=control_descriptor,
LOGGING_API_SERVICE_DESCRIPTOR=logging_descriptor,
PIPELINE_OPTIONS=pipeline_options)
# only add worker_id when it is set.
if self._worker_id:
env_dict['WORKER_ID'] = self._worker_id
with worker_handlers.SUBPROCESS_LOCK:
p = subprocess.Popen(self._worker_command_line, shell=True, env=env_dict)
try:
p.wait()
if p.returncode:
raise RuntimeError(
'Worker subprocess exited with return code %s' % p.returncode)
finally:
if p.poll() is None:
p.kill()
logging_server.stop(0)
class BeamJob(abstract_job_service.AbstractBeamJob):
"""This class handles running and managing a single pipeline.
The current state of the pipeline is available as self.state.
"""
def __init__(
self,
job_id: str,
pipeline,
options,
provision_info: fn_runner.ExtendedProvisionInfo,View on GitHub (pinned to 12126d8942)