{"record":{"id":"e579ced3c2729b20","repo":"apache/beam","slug":"circular-reference-detected-transform-name-references-itself","errorCode":null,"errorMessage":"Circular reference detected: Transform {name} references itself as input in {identify_object(spec)}","messagePattern":"Circular reference detected: Transform (.+?) references itself as input in (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/yaml/yaml_transform.py","lineNumber":1363,"sourceCode":"        if language == 'generic':\n          raise ValueError(f'Missing language for {identify_object(spec)}')\n        else:\n          raise ValueError(\n              f'Unknown language {language} for {identify_object(spec)}')\n      return dict(spec, type=new_type, name=spec.get('name', spec['type']))\n    else:\n      return spec\n\n  def validate_transform_references(spec):\n    name = spec.get('name', '')\n    transform_type = spec.get('type')\n    inputs = spec.get('input').get('input', [])\n\n    if not is_empty(inputs):\n      input_values = [inputs] if isinstance(inputs, str) else inputs\n      for input_value in input_values:\n        if input_value in (name, transform_type):\n          raise ValueError(\n              f\"Circular reference detected: Transform {name} \"\n              f\"references itself as input in {identify_object(spec)}\")\n\n    return spec\n\n  for phase in [\n      ensure_transforms_have_types,\n      normalize_mapping,\n      normalize_combine,\n      preprocess_languages,\n      ensure_transforms_have_providers,\n      preprocess_source_sink,\n      preprocess_chain,\n      tag_explicit_inputs,\n      normalize_inputs_outputs,\n      validate_transform_references,\n      preprocess_flattened_inputs,\n      ensure_errors_consumed,","sourceCodeStart":1345,"sourceCodeEnd":1381,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/yaml/yaml_transform.py#L1345-L1381","documentation":"Beam YAML's transform-reference validation raises this when a pipeline transform lists itself (by name or transform type) as one of its own inputs, in validate_transform_references. Self-referencing inputs create an unresolvable dependency cycle, so the graph can never be evaluated and validation fails fast.","triggerScenarios":"A YAML transform spec has an 'input' (or input.input list) whose value equals the transform's own 'name' or its 'type' string; raised during graph expansion of the pipeline spec.","commonSituations":"Copy-pasted YAML where a transform's input was accidentally left pointing at itself; templated/generated YAML that substitutes the same name into both name and input fields; typos in the input field naming the wrong transform.","solutions":["Edit the YAML so the transform's input points to the correct upstream transform, not itself.","If the transform should read from the pipeline source, set input to the actual source transform name.","Rename the transform so its name no longer collides with the intended input reference, then update the input."],"exampleFix":"// before\n- name: MyTransform\n  type: MapToFields\n  input: MyTransform\n  config: {...}\n// after\n- name: MyTransform\n  type: MapToFields\n  input: ReadFromPubSub\n  config: {...}","handlingStrategy":"validation","validationCode":"def check_no_self_reference(transform):\n    inputs = transform.get('input', {}).get('input', [])\n    inputs = [inputs] if isinstance(inputs, str) else (inputs or [])\n    for ref in inputs:\n        if ref in (transform.get('name'), transform.get('type')):\n            raise ValueError(f\"{transform.get('name')} references itself via input '{ref}'\")","typeGuard":"def is_self_reference(t):\n    ins = t.get('input', {}).get('input', [])\n    ins = [ins] if isinstance(ins, str) else (ins or [])\n    return any(r in (t.get('name'), t.get('type')) for r in ins)","tryCatchPattern":"try:\n    expand_pipeline(yaml_spec)\nexcept ValueError as e:\n    if 'Circular reference detected' in str(e):\n        print(f'Fix self-referencing input in YAML: {e}')","preventionTips":["Lint YAML pipelines for name/input collisions before submission.","Keep transform names distinct from their upstream source names.","Validate pipelines with Beam's YAML validation API in CI."],"tags":["beam-yaml","pipeline-validation","circular-reference","config"],"backgroundTag":"circular-reference-detected","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"}