apache/beam · error · ValueError

"IQR.score_one expected univariate input, but got

Error message

"IQR.score_one expected univariate input, but got %s", str(x)

What it means

IQR.score_one computes the anomaly score for one data point and expects a univariate beam.Row with exactly one field. If the row's __dict__ does not have exactly one entry, a ValueError is raised. This ensures scoring uses a single numeric value as the IQR math requires.

Solutions

  1. Map the input to a single-field Row before scoring: beam.Map(lambda r: beam.Row(value=r.metric)).
  2. Keep learn_one and score_one inputs shaped identically (same single field).
  3. Choose a multivariate detector if scoring requires multiple simultaneous features.

Example fix

// before
rows | beam.Map(detector.score_one)
// after
rows | beam.Map(lambda r: beam.Row(v=r.metric)) | beam.Map(detector.score_one)
Defensive patterns

Strategy: validation

Validate before calling

if len(row.__dict__) != 1:
    raise ValueError(f"IQR.score_one requires exactly one field, got: {list(row.__dict__)}")

Type guard

def is_univariate(row): return len(getattr(row, '__dict__', {})) == 1

Try / catch

try:
    score = detector.score_one(row)
except ValueError as e:
    score = None
    logger.warning("unscorable row %r: %s", row, e)

Prevention

When it happens

Trigger: Scoring a beam.Row containing multiple attributes or an empty row via IQR.score_one, typically when the same PCollection feeding learn_one was reshaped or when scoring rows straight from a multi-column source.

Common situations: Pipeline reads a table with several numeric columns and pipes all of them into score_one; schema evolution adds a column; users pass the original row instead of a projected single-value 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/bd77914446d982e7. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/ml/anomaly/detectors/iqr.py:104

    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))

    v = next(iter(x))
    if v is None or math.isnan(v):
      return None

    q1 = self._q1_tracker.get()
    q3 = self._q3_tracker.get()

    # not enough data points to compute median or median absolute deviation
    if math.isnan(q1) or math.isnan(q3):
      return float('NaN')

    iqr = q3 - q1
    if abs(iqr) < EPSILON:
      return 0.0

    if v > q3:

View on GitHub (pinned to 12126d8942)