apache/beam · error · ValueError
"IQR.learn_one expected univariate input, but got
Error message
"IQR.learn_one expected univariate input, but got %s", str(x)
What it means
IQR.learn_one updates the Q1/Q3 quantile trackers and expects x to be a beam.Row with exactly one field (univariate). If the row has zero or multiple fields, a ValueError is raised. This guards the IQR detector, which mathematically only operates on a single value per data point.
Solutions
- Project the input to a single numeric field, e.g. rows | beam.Map(lambda r: beam.Row(value=r.value)).
- Split multi-column data into separate detector pipelines, one per metric.
- Use a multivariate-capable detector if the input is intentionally multi-dimensional.
Example fix
# before pc | anomaly.IQR(overrides).learn_one() # Row(value=1.0, label='x') # after pc | beam.Map(lambda r: beam.Row(value=r.value)) | anomaly.IQR(overrides).learn_one()
Defensive patterns
Strategy: validation
Validate before calling
if len(row.__dict__) != 1:
raise ValueError(f"IQR.learn_one requires exactly one field, got: {list(row.__dict__)}") Type guard
def is_univariate(row): return len(getattr(row, '__dict__', {})) == 1 Try / catch
try:
detector.learn_one(row)
except ValueError as e:
logger.warning("skipping non-univariate row %r: %s", row, e) Prevention
- Always project multi-column PCollections to a single-field beam.Row before detectors
- Keep learn/score shaping in one shared transform
- Add schema assertions after any join or enrichment step
When it happens
Trigger: Passing a beam.Row with more than one attribute (multivariate input) or an empty row to IQR.learn_one, e.g. beam.Row(value=..., timestamp=...) fed directly into the detector's learn step.
Common situations: Users convert a multi-column PCollection into a Row without projecting down to one numeric column; a pipeline schema change adds a second field to the Row; accidentally passing a named tuple or dict-backed Row with metadata fields.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- "IQR.score_one expected univariate input, but got
- "RobustZScore.learn_one expected univariate input, but got
- "RobustZScore.score_one expected univariate input, but got
- ZScore.learn_one expected univariate input, but got
- ZScore.score_one expected univariate input, but got
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ca85cdd31c8d51f2.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/ml/anomaly/detectors/iqr.py:87
self._q1_tracker = q1_tracker or \
BufferedSlidingQuantileTracker(DEFAULT_WINDOW_SIZE, 0.25)
assert self._q1_tracker._q == 0.25, \
"q1_tracker must be initialized with q = 0.25"
self._q3_tracker = q3_tracker or \
SecondaryBufferedQuantileTracker(self._q1_tracker, 0.75)
assert self._q3_tracker._q == 0.75, \
"q3_tracker must be initialized with q = 0.75"
def learn_one(self, x: beam.Row) -> None:
"""Updates the quantile trackers with a new data point.
Args:
x: A `beam.Row` containing a single numerical value.
"""
if len(x.__dict__) != 1:
raise ValueError(
"IQR.learn_one expected univariate input, but got %s", str(x))
v = next(iter(x))
self._q1_tracker.push(v)
self._q3_tracker.push(v)
def score_one(self, x: beam.Row) -> Optional[float]:
"""Scores a data point based on its deviation from the IQR.
Args:
x: A `beam.Row` containing a single numerical value.
Returns:
float | None: The anomaly score.
"""
if len(x.__dict__) != 1:
raise ValueError(
"IQR.score_one expected univariate input, but got %s", str(x))View on GitHub (pinned to 12126d8942)