{"record":{"id":"455f3d5b4ac5ffdf","repo":"apache/beam","slug":"ambiguity-due-to-non-preserved-tags-s-vs-s","errorCode":null,"errorMessage":"Ambiguity due to non-preserved tags: %s vs %s","messagePattern":"Ambiguity due to non-preserved tags: (.+?) vs (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/external.py","lineNumber":921,"sourceCode":"      return env\n\n    for env in components.environments.values():\n      _resolve_artifacts_for(env)\n    return components\n\n  def _output_to_pvalueish(self, output_dict):\n    if len(output_dict) == 1:\n      return next(iter(output_dict.values()))\n    else:\n      return output_dict\n\n  def to_runner_api_transform(self, context, full_label):\n    pcoll_renames = {}\n    renamed_tag_seen = False\n    for tag, pcoll in self._inputs.items():\n      if tag not in self._expanded_transform.inputs:\n        if renamed_tag_seen:\n          raise RuntimeError(\n              'Ambiguity due to non-preserved tags: %s vs %s' % (\n                  sorted(self._expanded_transform.inputs.keys()),\n                  sorted(self._inputs.keys())))\n        else:\n          renamed_tag_seen = True\n          tag, = self._expanded_transform.inputs.keys()\n      pcoll_renames[self._expanded_transform.inputs[tag]] = (\n          context.pcollections.get_id(pcoll))\n    for tag, pcoll in self._outputs.items():\n      pcoll_renames[self._expanded_transform.outputs[tag]] = (\n          context.pcollections.get_id(pcoll))\n\n    def _equivalent(coder1, coder2):\n      return coder1 == coder2 or _normalize(coder1) == _normalize(coder2)\n\n    def _normalize(coder_proto):\n      normalized = copy.copy(coder_proto)\n      normalized.spec.environment_id = ''","sourceCodeStart":903,"sourceCodeEnd":939,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/external.py#L903-L939","documentation":"When re-wiring an externally expanded transform back into the pipeline graph, an input tag no longer matches after tag renaming and this happened for a second time; the runner cannot tell which PCollection the renamed tag corresponds to, so the mapping is ambiguous.","triggerScenarios":"Thrown at sdks/python/apache_beam/transforms/external.py:921 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Report to Beam devs: non-preserved tags are an expansion-service protocol edge case","As a workaround, avoid multi-input external transforms with duplicated/renamed tags"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}