{"record":{"id":"bd77914446d982e7","repo":"apache/beam","slug":"iqr-score-one-expected-univariate-input-but-got-s-str-x","errorCode":null,"errorMessage":"\"IQR.score_one expected univariate input, but got %s\", str(x)","messagePattern":"\"IQR\\.score_one expected univariate input, but got (.+?)\", str\\(x\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/anomaly/detectors/iqr.py","lineNumber":104,"sourceCode":"    if len(x.__dict__) != 1:\n      raise ValueError(\n          \"IQR.learn_one expected univariate input, but got %s\", str(x))\n\n    v = next(iter(x))\n    self._q1_tracker.push(v)\n    self._q3_tracker.push(v)\n\n  def score_one(self, x: beam.Row) -> Optional[float]:\n    \"\"\"Scores a data point based on its deviation from the IQR.\n\n    Args:\n      x: A `beam.Row` containing a single numerical value.\n\n    Returns:\n      float | None: The anomaly score.\n    \"\"\"\n    if len(x.__dict__) != 1:\n      raise ValueError(\n          \"IQR.score_one expected univariate input, but got %s\", str(x))\n\n    v = next(iter(x))\n    if v is None or math.isnan(v):\n      return None\n\n    q1 = self._q1_tracker.get()\n    q3 = self._q3_tracker.get()\n\n    # not enough data points to compute median or median absolute deviation\n    if math.isnan(q1) or math.isnan(q3):\n      return float('NaN')\n\n    iqr = q3 - q1\n    if abs(iqr) < EPSILON:\n      return 0.0\n\n    if v > q3:","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/anomaly/detectors/iqr.py#L86-L122","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Map the input to a single-field Row before scoring: beam.Map(lambda r: beam.Row(value=r.metric)).","Keep learn_one and score_one inputs shaped identically (same single field).","Choose a multivariate detector if scoring requires multiple simultaneous features."],"exampleFix":"// before\nrows | beam.Map(detector.score_one)\n// after\nrows | beam.Map(lambda r: beam.Row(v=r.metric)) | beam.Map(detector.score_one)","handlingStrategy":"validation","validationCode":"if len(row.__dict__) != 1:\n    raise ValueError(f\"IQR.score_one requires exactly one field, got: {list(row.__dict__)}\")","typeGuard":"def is_univariate(row): return len(getattr(row, '__dict__', {})) == 1","tryCatchPattern":"try:\n    score = detector.score_one(row)\nexcept ValueError as e:\n    score = None\n    logger.warning(\"unscorable row %r: %s\", row, e)","preventionTips":["Project rows to one numeric field immediately before scoring","Mirror the learn-stage projection in the score stage","Filter out metadata columns before detector transforms"],"tags":["python","anomaly-detection","validation","univariate"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}