{"record":{"id":"892aa034829d7950","repo":"apache/beam","slug":"id-s-is-already-taken","errorCode":null,"errorMessage":"Id '%s' is already taken.","messagePattern":"Id '(.+?)' is already taken\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/pipeline_context.py","lineNumber":143,"sourceCode":"          return id\n    return self.put_proto(\n        self._pipeline_context.component_id_map.get_or_assign(\n            obj=obj, obj_type=self._obj_type, label=label),\n        maybe_new_proto)\n\n  def get_id_to_proto_map(self) -> dict[str, message.Message]:\n    return self._id_to_proto\n\n  def get_proto_from_id(self, id: str) -> message.Message:\n    return self.get_id_to_proto_map()[id]\n\n  def put_proto(\n      self,\n      id: str,\n      proto: message.Message,\n      ignore_duplicates: bool = False) -> str:\n    if not ignore_duplicates and id in self._id_to_proto:\n      raise ValueError(\"Id '%s' is already taken.\" % id)\n    elif (ignore_duplicates and id in self._id_to_proto and\n          self._id_to_proto[id] != proto):\n      raise ValueError(\n          'Cannot insert different protos %r and %r with the same ID %r',\n          self._id_to_proto[id],\n          proto,\n          id)\n    self._id_to_proto[id] = proto\n    return id\n\n  def __getitem__(self, id: str) -> Any:\n    return self.get_by_id(id)\n\n  def __contains__(self, id: str) -> bool:\n    return id in self._id_to_proto\n\n\nclass PipelineContext(object):","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/pipeline_context.py#L125-L161","documentation":"PipelineContext.put_proto registers a proto under an id; by default, inserting an id that is already taken raises ValueError(\"Id '%s' is already taken.\"). This guards against silently overwriting pipeline components (transforms, pcollections) referenced by id.","triggerScenarios":"Calling context.put_proto(id, proto) with an id already present in the context, e.g. re-adding a component during pipeline construction or re-hydrating a pipeline from proto with clashing ids, without ignore_duplicates=True.","commonSituations":"Custom runner/tooling code that manipulates PipelineContext directly; reconstructing pipelines from serialized protos where two components got the same id; calling get_by_proto (which auto-assigns via put_proto) for a proto already registered under a different id.","solutions":["Pass ignore_duplicates=True when re-registering an identical proto under an existing id is acceptable","Generate a fresh unique id instead of reusing the existing one","Look up the existing component with context.get_by_id(id) instead of inserting again","Check why ids collide (e.g. pipeline construction or proto deserialization generating duplicate ids)"],"exampleFix":"// before\ncontext.put_proto('transform_1', proto)  # raises if taken\n// after\ncontext.put_proto('transform_1', proto, ignore_duplicates=True)","handlingStrategy":"try-catch","validationCode":"if id in context._id_to_proto:\n    id = context.next_id()  # or reuse get_by_id(id)","typeGuard":null,"tryCatchPattern":"try:\n    context.put_proto(id, proto)\nexcept ValueError as e:\n    if 'already taken' in str(e):\n        context.put_proto(context.next_id(), proto)","preventionTips":["Use context.next_id() or unique-id helpers instead of hand-picked ids","Pass ignore_duplicates=True only when re-inserting an identical proto","Check context.get_by_id(id) before inserting","Audit pipeline deserialization code for duplicate id generation"],"tags":["pipeline","context","duplicate-id"],"backgroundTag":"invalid-identifier","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"}