Summary
Using TaskHandler as a context manager (with TaskHandler(...) as th:) without calling th.start_processes() inside the block silently starts zero workers. No error is raised. The workflow hangs in RUNNING state indefinitely. The context manager gives no indication it hasn't started anything.
Steps to reproduce
from conductor.client.automator.task_handler import TaskHandler
from conductor.client.configuration.configuration import Configuration
from conductor.client.orkes_clients import OrkesClients
from conductor.client.worker.worker_task import worker_task
@worker_task(task_definition_name='my_worker', register_task_def=True)
def my_worker(name: str) -> str:
return f'Hello {name}'
config = Configuration()
executor = OrkesClients(configuration=config).get_workflow_executor()
# ... register workflow ...
with TaskHandler(configuration=config, scan_for_annotated_workers=True) as th:
# Forgot to call th.start_processes()
run = executor.execute(name='my_workflow', version=1, workflow_input={'name': 'x'})
print(run.status) # RUNNING — workflow stuck, never completed
What happens
TaskHandler initialized
Starting worker processes... Started 0 TaskRunner process(es) ← silent
Status: RUNNING
Actually the "Starting worker processes" log is NOT printed because start_processes() was never called. Workers were never started. The workflow queues a task, no worker picks it up, and execute() times out returning RUNNING.
Why this is confusing
In Python, context managers conventionally handle setup in __enter__. A user reading:
with TaskHandler(configuration=config, scan_for_annotated_workers=True) as th:
th.start_processes()
naturally wonders: why do I need to call start_processes() explicitly when I'm already inside the with block? The answer (the with only ensures cleanup/stop on exit, not startup) is not documented at the point of use.
This leads to two failure modes:
- Skip
start_processes() entirely → 0 workers, workflow hangs
- Move
start_processes() outside the with block → workers not cleaned up properly on exception
Expected behavior
Either:
__enter__ should call start_processes() automatically (conventional Python behavior)
- Or the context manager should warn/raise if
start_processes() was never called before execute() is invoked
At minimum, the docstring/README should explicitly warn that start_processes() is required inside the with block and explain why.
Environment
- Python 3.14, conductor-python 1.3.8, Conductor OSS
Summary
Using
TaskHandleras a context manager (with TaskHandler(...) as th:) without callingth.start_processes()inside the block silently starts zero workers. No error is raised. The workflow hangs inRUNNINGstate indefinitely. The context manager gives no indication it hasn't started anything.Steps to reproduce
What happens
Actually the "Starting worker processes" log is NOT printed because
start_processes()was never called. Workers were never started. The workflow queues a task, no worker picks it up, andexecute()times out returningRUNNING.Why this is confusing
In Python, context managers conventionally handle setup in
__enter__. A user reading:naturally wonders: why do I need to call
start_processes()explicitly when I'm already inside thewithblock? The answer (thewithonly ensures cleanup/stop on exit, not startup) is not documented at the point of use.This leads to two failure modes:
start_processes()entirely → 0 workers, workflow hangsstart_processes()outside thewithblock → workers not cleaned up properly on exceptionExpected behavior
Either:
__enter__should callstart_processes()automatically (conventional Python behavior)start_processes()was never called beforeexecute()is invokedAt minimum, the docstring/README should explicitly warn that
start_processes()is required inside thewithblock and explain why.Environment