apache/beam · error · RuntimeError

No IO transform feeds

Error message

No IO transform feeds %s

What it means

input_for maps a transform's deferred input to the GRPC read (data channel) transform that feeds it by scanning the ProcessBundleDescriptor. If no DATA_INPUT_URN transform consumes that input, there is no channel wired for it and this RuntimeError is thrown.

Solutions

  1. Upgrade apache-beam to a version fixing stage/split graph wiring
  2. Reproduce with --experiments=beam_fn_api_use_transform_for_resquad to alter residual handling
  3. Inspect the ProcessBundleDescriptor to confirm the transform_id's outputs and data channels
  4. File a Beam issue with the pipeline and stage dumps if reproducible
Defensive patterns

Strategy: try-catch

Try / catch

try:
    input_ref = ctx.input_for(transform_id)
except RuntimeError as e:
    if 'No IO transform feeds' in str(e):
        rebuild_bundle_descriptor(ctx)
    raise

Prevention

When it happens

Trigger: Residuals or SDK-delayed applications reference an input transform_id for which no matching data-input read exists in the bundle descriptor — e.g. after graph rewrites removed or renamed the channel.

Common situations: Split/residual processing after optimization stages altered the graph; cross-language pipelines where channel naming mismatches; runner-internal bugs in stage construction.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/e6584c3960f86068. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/runners/portability/fn_api_runner/execution.py:1180

    for read_id, proto in self.process_bundle_descriptor.transforms.items():
      # The GrpcRead is followed by the SDF/Process.
      if (proto.spec.urn == bundle_processor.DATA_INPUT_URN and
          input_pcoll in proto.outputs.values()):
        return read_id
      # The GrpcRead is followed by the SDF/Truncate -> SDF/Process.
      if (proto.spec.urn
          == common_urns.sdf_components.TRUNCATE_SIZED_RESTRICTION.urn and
          input_pcoll in proto.outputs.values()):
        read_input = list(
            self.process_bundle_descriptor.transforms[read_id].inputs.values()
        )[0]
        for (grpc_read,
             transform_proto) in self.process_bundle_descriptor.transforms.items():  # pylint: disable=line-too-long
          if (transform_proto.spec.urn == bundle_processor.DATA_INPUT_URN and
              read_input in transform_proto.outputs.values()):
            return grpc_read

    raise RuntimeError('No IO transform feeds %s' % transform_id)

View on GitHub (pinned to 12126d8942)