{"record":{"id":"a50601c3dcef3f8c","repo":"apache/beam","slug":"expected-a-single-pcollection-output-but-got-output-perhaps","errorCode":null,"errorMessage":"Expected a single PCollection output, but got ${output}. Perhaps withMultipleOutputs() needs to be specified?","messagePattern":"Expected a single PCollection output, but got (.+?)\\. Perhaps withMultipleOutputs\\(\\) needs to be specified\\?","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/yaml/src/main/java/org/apache/beam/sdk/extensions/yaml/YamlTransform.java","lineNumber":175,"sourceCode":"    PTransform externalTransform =\n        PythonExternalTransform.from(\"apache_beam.yaml.yaml_transform.YamlTransform\")\n            .withArgs(yamlDefinition)\n            .withExtraPackages(ImmutableList.of(\"jinja2\", \"pyyaml\", \"virtualenv-clone\"));\n    if (input instanceof PBegin) {\n      output = ((PBegin) input).apply(externalTransform);\n    } else if (input instanceof PCollection) {\n      output = ((PCollection<?>) input).apply(externalTransform);\n    } else if (input instanceof PCollection) {\n      output = ((PCollection<?>) input).apply(externalTransform);\n    } else if (input instanceof PCollectionRowTuple) {\n      output = ((PCollectionRowTuple) input).apply(externalTransform);\n    } else {\n      throw new IllegalArgumentException(\"Unrecognized input type: \" + input);\n    }\n\n    if (outputTags == null) {\n      if (!(output instanceof PCollection)) {\n        throw new IllegalArgumentException(\n            \"Expected a single PCollection output, but got \"\n                + output\n                + \". Perhaps withMultipleOutputs() needs to be specified?\");\n      }\n      return (OutputT) output;\n    } else {\n      if (output instanceof PCollection) {\n        // ExternalPythonTransform always returns single outputs as PCollections.\n        if (outputTags.size() != 1) {\n          throw new IllegalArgumentException(\n              \"Expected \" + outputTags.size() + \" outputs, but got exactly one.\");\n        }\n        return (OutputT)\n            PCollectionRowTuple.of(outputTags.iterator().next(), (PCollection<Row>) output);\n      } else {\n        Map<TupleTag<?>, PValue> expandedOutputs = output.expand();\n        Set<String> actualOutputTags =\n            expandedOutputs.keySet().stream()","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/yaml/src/main/java/org/apache/beam/sdk/extensions/yaml/YamlTransform.java#L157-L193","documentation":"When the YAML transform declares no multiple output tags, expand() expects the underlying external transform to produce exactly one PCollection. If the returned value is a multi-output PCollectionTuple/PCollectionRowTuple instead, the library throws, hinting that the transform was configured for multiple outputs.","triggerScenarios":"Applying a YamlTransform whose underlying external (e.g. Python) transform returns multiple outputs (via withMultipleOutputs) while the Java-side outputTags spec is null/absent.","commonSituations":"YAML spec drift: the external transform was changed to emit several named outputs but the YAML/Java wrapper still declares a single output; copy-pasting a multi-output transform config into a single-output pipeline.","solutions":["Declare the multiple output tags in the YAML/Java config (set outputTags) so multi-output is expected.","Configure the external transform for a single output if only one result is needed.","Update the pipeline consumer to handle the PCollectionRowTuple of outputs explicitly.","Check the external transform's withMultipleOutputs usage and remove it for single-output usage."],"exampleFix":"// before (multi-output transform, single-output spec)\nyamlTransform.withOutputTags(null);\n// after\nyamlTransform.withOutputTags(new TupleTag<>(\"main\"), ImmutableList.of(new TupleTag<>(\"side\")));","handlingStrategy":"validation","validationCode":"if (specOutputTags == null && !(externalTransformSupportsSingleOutput())) {\n  throw new IllegalStateException(\"Declare outputTags for multi-output transform\");\n}","typeGuard":"boolean isSingleOutput(Object output) { return output instanceof PCollection; }","tryCatchPattern":"try {\n  return expand(input);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"withMultipleOutputs\")) { /* declare output tags */ }\n  throw e;\n}","preventionTips":["Keep outputTags declaration in sync with the external transform's actual outputs","Document whether the Python transform uses withMultipleOutputs","Test YAML transforms end-to-end in CI"],"tags":["apache-beam","java","yaml-transform","multiple-outputs"],"backgroundTag":"unexpected-response-shape","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"}