apache/beam · critical · Exception
Requested execution of a stateful DoFn, but no user state…
Error message
Requested execution of a stateful DoFn, but no user state context is available. This likely means that the current runner does not support the execution of stateful DoFns.
What it means
Beam raises this when a DoFn is marked stateful (uses StateParam/TimerParam) but DoFnInvoker is created without a user_state_context, which supplies state/timer access backed by the runner. Without it, state and timer parameters cannot be fulfilled, so construction fails early with this exception.
Solutions
- Run on a runner that supports stateful DoFns (e.g. Dataflow/Flink/Spark with state support, DirectRunner where applicable) and pass a user_state_context to create_invoker
- In tests, supply a mock/fake UserStateContext when constructing the invoker
- If state is not actually required, refactor the DoFn to be stateless
Example fix
# before
invoker = DoFnInvoker.create_invoker(sig, output_processor=...) # no context
# after
invoker = DoFnInvoker.create_invoker(
sig,
output_processor=...,
user_state_context=my_user_state_context) Defensive patterns
Strategy: validation
Validate before calling
def assert_state_supported(dofn_signature, context):
if dofn_signature.is_stateful_dofn() and context is None:
raise Exception('Stateful DoFn requires a runner/UserStateContext that supports state') Type guard
def runner_supports_state(runner_name):
return runner_name in ('DirectRunner', 'DataflowRunner', 'FlinkRunner', 'SparkRunner') Try / catch
try:
invoker = DoFnInvoker.create_invoker(sig, output_processor=proc,
user_state_context=ctx)
except Exception as e:
if 'no user state context' in str(e):
logging.error('Runner does not support stateful DoFns; switch runner or refactor to stateless')
raise Prevention
- Verify runner stateful-DoFn support before adding StateParam/TimerParam
- Pass a user_state_context (real or fake) whenever invoking stateful DoFns in tests
- Gate stateful features with a pipeline-option check at job construction
When it happens
Trigger: Using DoFnInvoker.create_invoker (or a runner path) for a stateful DoFn without passing a user_state_context (e.g. running on a runner or test harness that lacks state support).
Common situations: Running stateful pipelines on runners without stateful DoFn support (some batch/direct/test harnesses or older runner versions); unit-testing stateful DoFns with plain create_invoker and no UserStateContext; missing --streaming or state flags on runners that gate the feature.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- Invalid state spec
- A BigQuery table or a query must be specified
- A cluster_identifier should be Optional[Union[str…
- A context manager constructor (not a fully constructed…
- A has been supplied to the model handler, but the required…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/310cbd02b720dcf0.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/runners/common.py:1494
output_handler = _OutputHandler(
windowing.windowfn,
main_receivers,
tagged_receivers,
per_element_output_counter,
getattr(fn, 'output_batch_converter', None),
getattr(
do_fn_signature.process_method.method_value,
'_beam_yields_batches',
False),
getattr(
do_fn_signature.process_batch_method.method_value,
'_beam_yields_elements',
False),
check_user_dofn_output=check_user_dofn_output,
)
if do_fn_signature.is_stateful_dofn() and not user_state_context:
raise Exception(
'Requested execution of a stateful DoFn, but no user state context '
'is available. This likely means that the current runner does not '
'support the execution of stateful DoFns.')
self.do_fn_invoker = DoFnInvoker.create_invoker(
do_fn_signature,
output_handler,
self.context,
side_inputs,
args,
kwargs,
user_state_context=user_state_context,
bundle_finalizer_param=self.bundle_finalizer_param)
def process(self, windowed_value):
# type: (WindowedValue) -> Iterable[SplitResultResidual]
try:
return self.do_fn_invoker.invoke_process(windowed_value)View on GitHub (pinned to 12126d8942)