{"record":{"id":"667caef9c3674070","repo":"apache/beam","slug":"key-key-maps-to-multiple-model-handlers-all-keys-must-map-to","errorCode":null,"errorMessage":"key {key} maps to multiple model handlers. All keys must map to exactly one model handler.","messagePattern":"key (.+?) maps to multiple model handlers\\. All keys must map to exactly one model handler\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/ml/inference/base.py","lineNumber":828,"sourceCode":"      env_vars = getattr(mh, '_env_vars', {})\n      if len(env_vars) > 0:\n        logging.warning(\n            'mh %s defines the following _env_vars which will be ignored %s. '\n            '_env_vars are not respected when more than one model handler is '\n            'used in a KeyedModelHandler. If you need env vars set at '\n            'inference time, you can do so with '\n            'a custom inference function.',\n            mh,\n            env_vars)\n\n      if len(keys) == 0:\n        raise ValueError(\n            f'Empty list maps to model handler {mh}. All model handlers must '\n            'have one or more associated keys.')\n      self._id_to_mh_map[keys[0]] = mh\n      for key in keys:\n        if key in self._key_to_id_map:\n          raise ValueError(\n              f'key {key} maps to multiple model handlers. All keys must map '\n              'to exactly one model handler.')\n        self._key_to_id_map[key] = keys[0]\n\n  def load_model(self) -> Union[ModelT, _ModelHandlerManager]:\n    if self._single_model:\n      return self._unkeyed.load_model()\n    return _ModelHandlerManager(self._id_to_mh_map)\n\n  def run_inference(\n      self,\n      batch: Sequence[tuple[KeyT, ExampleT]],\n      model: Union[ModelT, _ModelHandlerManager],\n      inference_args: Optional[dict[str, Any]] = None\n  ) -> Iterable[tuple[KeyT, PredictionT]]:\n    if self._single_model:\n      keys, unkeyed_batch = zip(*batch)\n      return zip(","sourceCodeStart":810,"sourceCodeEnd":846,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/ml/inference/base.py#L810-L846","documentation":"Each key in a multi-handler KeyedModelHandler must map to exactly one model handler, since the key alone determines which handler processes an element. If the same key appears in the lists of two different handlers, the routing would be ambiguous and a ValueError is raised.","triggerScenarios":"KeyedModelHandler([KeyedModelHandlerTuple(mh1, ['a','b']), KeyedModelHandlerTuple(mh2, ['b','c'])]) — key 'b' appears in both tuples.","commonSituations":"Overlapping cohorts from config files; copy-paste of key lists between handlers; generating cohorts from data where a key legitimately belongs to multiple groups but the API expects a partition.","solutions":["Deduplicate keys across tuples so each key belongs to exactly one handler.","Decide which handler should own the conflicting key and remove it from the other list.","Add a pre-construction check that the union of key lists has no duplicates."],"exampleFix":"# before\nKeyedModelHandler([\n  KeyedModelHandlerTuple(mh1, ['a', 'b']),\n  KeyedModelHandlerTuple(mh2, ['b', 'c'])])\n\n# after\nKeyedModelHandler([\n  KeyedModelHandlerTuple(mh1, ['a', 'b']),\n  KeyedModelHandlerTuple(mh2, ['c'])])","handlingStrategy":"validation","validationCode":"all_keys = [k for t in tuples for k in t.keys]\nassert len(all_keys) == len(set(all_keys)), f'Duplicate keys across handlers: {set(k for k in all_keys if all_keys.count(k) > 1)}'","typeGuard":"def keys_unique(tuples):\n    seen = set()\n    for t in tuples:\n        if seen & set(t.keys):\n            return False\n        seen.update(t.keys)\n    return True","tryCatchPattern":"try:\n    keyed = KeyedModelHandler(tuples)\nexcept ValueError as e:\n    if 'maps to multiple model handlers' in str(e):\n        raise ConfigError('Deduplicate keys across cohorts') from e\n    raise","preventionTips":["Ensure cohort definitions partition the key space without overlap.","Add a deduplication/assertion step when generating key lists from configs.","Keep a single source of truth for key-to-handler assignments."],"tags":["python","apache-beam","ml-inference","validation","duplicate-key"],"backgroundTag":"conflicting-config-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}