apache/beam · error · ValueError
DoFn.WatermarkEstimatorParam…
Error message
DoFn.WatermarkEstimatorParam expectedWatermarkEstimatorProvider object.
What it means
ValueError raised by `_WatermarkDoFnParam.__init__` (exposed as `DoFn.WatermarkEstimatorParam`) when the supplied watermark_estimator_provider is not `None` and is not an instance of `WatermarkEstimatorProvider`. Only a provider instance (or None) is accepted for watermark estimator parameters.
Solutions
- Pass an instance of a class subclassing `WatermarkEstimatorProvider`, or use the built-in `WatermarkEstimatorParam(lambda state: WatermarkEstimator(...))`-style helper that wraps a callable in a provider.
- Pass `None` if no custom estimator is needed.
- Ensure an instance (not the class) is passed.
Example fix
// before param = DoFn.WatermarkEstimatorParam(MyWatermarkEstimator) # class, not provider // after param = DoFn.WatermarkEstimatorParam(MyWatermarkEstimatorProvider()) # WatermarkEstimatorProvider instance
Defensive patterns
Strategy: type-guard
Validate before calling
from apache_beam.transforms.core import WatermarkEstimatorProvider
if provider is not None and not isinstance(provider, WatermarkEstimatorProvider):
raise TypeError('expected WatermarkEstimatorProvider instance') Type guard
from apache_beam.transforms.core import WatermarkEstimatorProvider
def is_watermark_provider(x) -> bool:
return x is None or isinstance(x, WatermarkEstimatorProvider) Try / catch
try:
param = DoFn.WatermarkEstimatorParam(provider)
except ValueError as e:
if 'WatermarkEstimatorProvider' in str(e):
provider = provider() if isinstance(provider, type) else None Prevention
- Subclass WatermarkEstimatorProvider rather than passing bare estimator functions or classes
- Pass None when no custom estimator is needed
- Double-check instance vs class when wiring DoFn params
When it happens
Trigger: Writing `DoFn.WatermarkEstimatorParam(MyEstimator)` or passing a class, callable, or estimator function instead of an object implementing `WatermarkEstimatorProvider` when declaring a DoFn with custom watermark estimation.
Common situations: Passing a watermark estimator factory function instead of a provider wrapping it; passing the class rather than an instance; confusion with `WatermarkEstimatorParam` expecting `WatermarkEstimatorProvider` (note the missing space in the message is cosmetic).
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- DoFn.RestrictionParam expected RestrictionProvider object.
- DoFn.StateParam expected StateSpec object.
- DoFn.TimerParam expected TimerSpec object.
- mismatched output type in method
- assign_context.window should not be None. This might be due…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/9d3b99e31745526e.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/transforms/core.py:526
def has_callbacks(self):
# type: () -> bool
return len(self._callbacks) > 0
def reset(self):
# type: () -> None
del self._callbacks[:]
class _WatermarkEstimatorParam(_DoFnParam):
"""WatermarkEstimator DoFn parameter."""
def __init__(
self,
watermark_estimator_provider: typing.
Optional[WatermarkEstimatorProvider] = None):
if (watermark_estimator_provider is not None and not isinstance(
watermark_estimator_provider, WatermarkEstimatorProvider)):
raise ValueError(
'DoFn.WatermarkEstimatorParam expected'
'WatermarkEstimatorProvider object.')
self.watermark_estimator_provider = watermark_estimator_provider
self.param_id = 'WatermarkEstimatorProvider'
class _ContextParam(_DoFnParam):
def __init__(
self, context_manager_constructor, args=(), kwargs=None, *, name=None):
class_name = self.__class__.__name__.strip('_')
if (not callable(context_manager_constructor) or
(hasattr(context_manager_constructor, '__enter__') and
len(inspect.signature(
context_manager_constructor.__enter__).parameters) == 0)):
# Context managers constructed with @contextlib.contextmanager can only
# be used once, and in addition cannot be pickled because they invoke
# the function on __init__ rather than at __enter__.
# In addition, other common context managers such asView on GitHub (pinned to 12126d8942)