apache/beam · error · ValueError

"RobustZScore.learn_one expected univariate input, but got

Error message

"RobustZScore.learn_one expected univariate input, but got %s", str(x)

What it means

RobustZScore.learn_one updates the MAD (median absolute deviation) tracker and requires x to be a beam.Row containing exactly one numerical value. A ValueError is raised when the row has any other number of fields. The robust z-score statistic is defined only for univariate input.

Solutions

  1. Project down to exactly one numeric field before learn_one: beam.Map(lambda r: beam.Row(value=r.measurement)).
  2. Verify the row schema with len(row.__dict__) == 1 in a preceding assert/validation step.
  3. Wrap multiple features into separate detector instances, one per feature.

Example fix

// before
beam.Row(value=1.0, unit="ms") | learn_one
// after
beam.Row(value=1.0) | learn_one
Defensive patterns

Strategy: validation

Validate before calling

if len(row.__dict__) != 1:
    raise ValueError(f"RobustZScore.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 row %r: %s", row, e)

Prevention

When it happens

Trigger: Calling RobustZScore.learn_one with a beam.Row having 0 or 2+ attributes, e.g. beam.Row(x=1, y=2) or a Row built from a multi-column PCollection element.

Common situations: Multi-feature datasets fed directly to the detector; rows that carry an ID alongside the value; upstream schema changes adding columns to the Row.

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/670c08d8be53fd1f. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/ml/anomaly/detectors/robust_zscore.py:81

  .. [#] Zhao, Y., Nasrullah, Z. and Li, Z.. (2019). PyOD: A Python Toolbox for Scalable Outlier Detection. Journal of machine learning research (JMLR), 20(96), pp.1-7.
  """
  # pylint: enable=line-too-long
  SCALE_FACTOR = 0.6745

  def __init__(self, mad_tracker: Optional[MadTracker] = None, **kwargs):
    if "threshold_criterion" not in kwargs:
      kwargs["threshold_criterion"] = FixedThreshold(3)
    super().__init__(**kwargs)
    self._mad_tracker = mad_tracker or MadTracker()

  def learn_one(self, x: beam.Row) -> None:
    """Updates the `MadTracker` with a new data point.

    Args:
      x: A `beam.Row` containing a single numerical value.
    """
    if len(x.__dict__) != 1:
      raise ValueError(
          "RobustZScore.learn_one expected univariate input, but got %s",
          str(x))

    v = next(iter(x))
    self._mad_tracker.push(v)

  def score_one(self, x: beam.Row) -> Optional[float]:
    """Scores a data point using the Robust Z-Score.

    Args:
      x: A `beam.Row` containing a single numerical value.

    Returns:
      float | None: The Robust Z-Score.
    """
    if len(x.__dict__) != 1:
      raise ValueError(
          "RobustZScore.score_one expected univariate input, but got %s",

View on GitHub (pinned to 12126d8942)