{"record":{"id":"6a7cd8acea958d53","repo":"apache/beam","slug":"type-annotation-for-multiple-outputs-is-not-allowed-yet-s","errorCode":null,"errorMessage":"type annotation for multiple outputs is not allowed yet: %s","messagePattern":"type annotation for multiple outputs is not allowed yet: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/portability/expansion_service.py","lineNumber":90,"sourceCode":"          request.components,\n          default_environment=self._default_environment,\n          namespace=request.namespace,\n          requirements=request.requirements)\n      producers = {\n          pcoll_id: (context.transforms.get_by_id(t_id), pcoll_tag)\n          for t_id, t_proto in request.components.transforms.items()\n          for pcoll_tag, pcoll_id in t_proto.outputs.items()\n      }\n      transform = with_pipeline(\n          ptransform.PTransform.from_runner_api(request.transform, context))\n      if len(request.output_coder_requests) == 1:\n        output_coder = {\n            k: context.element_type_from_coder_id(v)\n            for k, v in request.output_coder_requests.items()\n        }\n        transform = transform.with_output_types(list(output_coder.values())[0])\n      elif len(request.output_coder_requests) > 1:\n        raise ValueError(\n            'type annotation for multiple outputs is not allowed yet: %s' %\n            request.output_coder_requests)\n      inputs = transform._pvaluish_from_dict({\n          tag: with_pipeline(\n              context.pcollections.get_by_id(pcoll_id), pcoll_id)\n          for tag, pcoll_id in request.transform.inputs.items()\n      })\n      if not inputs:\n        inputs = pipeline\n      with external.ExternalTransform.outer_namespace(request.namespace):\n        result = pipeline.apply(\n            transform, inputs, request.transform.unique_name)\n      expanded_transform = pipeline._root_transform().parts[-1]\n      # TODO(BEAM-1833): Use named outputs internally.\n      if isinstance(result, dict):\n        expanded_transform.outputs = result\n      pipeline_proto = pipeline.to_runner_api(context=context)\n      # TODO(BEAM-1833): Use named inputs internally.","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/portability/expansion_service.py#L72-L108","documentation":"In the expansion service's Expand handler, when a transform carries output coder hints for more than one output, the service refuses to apply a with_output_types annotation (only single-output annotation is implemented) and raises ValueError. The expansion itself may be valid; only multi-output type annotation is unsupported.","triggerScenarios":"Calling the ExpansionService Expand RPC for a transform with len(request.output_coder_requests) > 1 — i.e. a multi-output transform (partition, multi-tag DoFn) with per-output coder hints.","commonSituations":"Cross-language expansion of multi-output transforms from an SDK that populates output_coder_requests for every tag; Java pipelines expanded via the Python expansion service with type hints on all outputs.","solutions":["Send at most one output coder request (for the main output) until multi-output annotation is supported.","Expand without output coder hints and set coders/types on the resulting PCollections afterwards.","Track/patch upstream expansion_service.py to add multi-output type annotation support."],"exampleFix":"// before\nrequest.output_coder_requests = {'out0': 'coder0', 'out1': 'coder1'}\n// after\nrequest.output_coder_requests = {}  # let the transform infer output types","handlingStrategy":"fallback","validationCode":"if len(request.output_coder_requests) > 1:\n    request.output_coder_requests = {}  # fall back to inference","typeGuard":null,"tryCatchPattern":"try:\n    result = expand_via_service(request)\nexcept ValueError as e:\n    if 'multiple outputs' in str(e):\n        request.output_coder_requests = {}\n        result = expand_via_service(request)\n    else:\n        raise","preventionTips":["Do not attach coder hints to every output tag of multi-output transforms.","Set output types on resulting PCollections after expansion instead.","Check the expansion service's supported features before relying on type annotation."],"tags":["python","apache-beam","cross-language","expansion-service"],"backgroundTag":"unsupported-operation","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"}