{"record":{"id":"2f4871d9c8bc2855","repo":"apache/beam","slug":"transform-node-r-was-not-replaced-as-expected","errorCode":null,"errorMessage":"Transform node %r was not replaced as expected.","messagePattern":"Transform node %r was not replaced as expected\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/pipeline.py","lineNumber":530,"sourceCode":"          side_input_replacements[transform_node] = new_side_inputs\n\n    self.visit(InputOutputUpdater(self))\n\n    for transform, output_replacement in output_replacements.items():\n      for tag, output in output_replacement:\n        transform.replace_output(output, tag=tag)\n\n    for transform, input_replacement in input_replacements.items():\n      transform.replace_inputs(input_replacement)\n\n    for transform, side_input_replacement in side_input_replacements.items():\n      transform.replace_side_inputs(side_input_replacement)\n\n  def _check_replacement(self, override: 'PTransformOverride') -> None:\n    class ReplacementValidator(PipelineVisitor):\n      def visit_transform(self, transform_node: AppliedPTransform) -> None:\n        if override.matches(transform_node):\n          raise RuntimeError(\n              'Transform node %r was not replaced as expected.' %\n              transform_node)\n\n    self.visit(ReplacementValidator())\n\n  def replace_all(self, replacements: Iterable['PTransformOverride']) -> None:\n    \"\"\" Dynamically replaces PTransforms in the currently populated hierarchy.\n\n    Currently this only works for replacements where input and output types\n    are exactly the same.\n\n    TODO: Update this to also work for transform overrides where input and\n    output types are different.\n\n    Args:\n      replacements (list[~apache_beam.pipeline.PTransformOverride]): a list of\n        :class:`~apache_beam.pipeline.PTransformOverride` objects.\n    \"\"\"","sourceCodeStart":512,"sourceCodeEnd":548,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/pipeline.py#L512-L548","documentation":"During pipeline construction Beam applies PTransformOverride replacements and then verifies (via _check_replacement) that no transform matching the override still exists in the graph. If a matching node survives, its replacement silently failed, so a RuntimeError is raised naming the node.","triggerScenarios":"A custom PTransformOverride whose replace() doesn't actually replace the matched node (e.g. returns the same transform, or the replacement re-matches the override pattern); incorrect matches() implementation that matches its own output.","commonSituations":"Writing custom overrides for portable/foreign-language transforms; Beam-internal replacement machinery failing after an SDK version change; overrides whose replacement transform still matches the same predicate.","solutions":["Ensure your PTransformOverride.replace() returns a transform that no longer matches matches().","Narrow matches() so the replacement output isn't matched again.","Check for duplicate/overlapping overrides in the replacement list.","If it comes from Beam internals, upgrade/downgrade the SDK — this often indicates an internal replacement bug; report with the transform detail."],"exampleFix":"// before\nclass BadOverride(PTransformOverride):\n  def matches(self, applied):\n    return isinstance(applied.transform, MyTransform)\n  def replace(self, applied):\n    return applied.transform  # no-op replacement\n// after\nclass GoodOverride(PTransformOverride):\n  def matches(self, applied):\n    return isinstance(applied.transform, MyTransform)\n  def replace(self, applied):\n    return MyReplacementTransform()  # different transform","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    pipeline.replace_all(replacements)\nexcept RuntimeError as e:\n    if 'was not replaced' in str(e):\n        # review override matches/replace pair\n        raise","preventionTips":["Ensure replace() output no longer matches matches()","Test custom PTransformOverrides in isolation","Keep overrides minimal and non-overlapping"],"tags":["python","apache-beam","runtime-error","transform-override"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}