{"record":{"id":"a4745351a9e6d88a","repo":"apache/beam","slug":"no-detectors-found-at-model-uuid","errorCode":null,"errorMessage":"No detectors found at {model_uuid}","messagePattern":"No detectors found at (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/anomaly/transforms.py","lineNumber":521,"sourceCode":"  \"\"\"Runs an ensemble of anomaly detectors on a PCollection of data.\n\n  This PTransform applies an `EnsembleAnomalyDetector` to the input data,\n  running each sub-detector and aggregating the results.\n\n  Args:\n    ensemble_detector: The `EnsembleAnomalyDetector` to run.\n  \"\"\"\n  def __init__(self, ensemble_detector: EnsembleAnomalyDetector):\n    self._ensemble_detector = ensemble_detector\n\n  def expand(\n      self, input: beam.PCollection[NestedKeyedInputT]\n  ) -> beam.PCollection[NestedKeyedOutputT]:\n    model_uuid = f\"{self._ensemble_detector._model_id}:{uuid.uuid4().hex[:6]}\"\n\n    assert self._ensemble_detector._sub_detectors is not None\n    if not self._ensemble_detector._sub_detectors:\n      raise ValueError(f\"No detectors found at {model_uuid}\")\n\n    results = []\n    for idx, detector in enumerate(self._ensemble_detector._sub_detectors):\n      if isinstance(detector, EnsembleAnomalyDetector):\n        results.append(\n            input\n            | f\"Run Ensemble Detector at index {idx} ({model_uuid})\" >>\n            RunEnsembleDetector(detector))\n      elif isinstance(detector, OfflineDetector):\n        results.append(\n            input\n            | f\"Run Offline Detector at index {idx} ({model_uuid})\" >>\n            RunOfflineDetector(detector))\n      else:\n        results.append(\n            input\n            | f\"Run One Detector at index {idx} ({model_uuid})\" >>\n            RunOneDetector(detector))","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/anomaly/transforms.py#L503-L539","documentation":"The Beam ML anomaly ensemble transform DoFn's expand() requires the EnsembleAnomalyDetector to have a non-empty _sub_detectors list. An empty list means there is nothing to fan out to, so it raises ValueError with the generated model_uuid for traceability.","triggerScenarios":"Constructing EnsembleAnomalyDetector(detectors=[]) (or equivalent aggregate detector like majority_vote/zscore with empty detector list) and running it through the ensemble transform.","commonSituations":"Building the detector list dynamically from config where all detectors were filtered out; YAML/JSON config parsed to an empty list; default constructor called without detectors.","solutions":["Pass at least one sub-detector: EnsembleAnomalyDetector(detectors=[ZScore(...), ...])","Validate the detector list is non-empty before building the pipeline","Fix the config-loading logic that produced an empty detectors collection"],"exampleFix":"// before\nens = EnsembleAnomalyDetector(detectors=[])\n\n// after\ndetectors = [ZScore(window_size=100), StandardDeviation(window_size=100)]\nif not detectors:\n    raise ValueError('at least one detector required')\nens = EnsembleAnomalyDetector(detectors=detectors)","handlingStrategy":"validation","validationCode":"if not ensemble._sub_detectors:\n    raise ValueError('EnsembleAnomalyDetector requires at least one sub-detector')","typeGuard":"def has_detectors(d) -> bool:\n    subs = getattr(d, '_sub_detectors', None)\n    return isinstance(subs, list) and len(subs) > 0","tryCatchPattern":"try:\n    result = pipeline | ensemble_transform\nexcept ValueError as e:\n    if 'No detectors found' in str(e):\n        logging.error('Configure at least one sub-detector: %s', e)","preventionTips":["Validate detector lists at config-load time","Never construct EnsembleAnomalyDetector with a literal empty list","Log the detector list during pipeline construction"],"tags":["python","apache-beam","anomaly-detection","configuration"],"backgroundTag":"empty-required-field","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"}