apache/beam · error · IllegalArgumentException

Could not find an output with tag for the transform

Error message

Could not find an output with tag  for the transform 

What it means

After verifying the tag exists in the expanded transform's outputsMap keySet, updateTransformViaTransformService looks up the replacement PCollection id via get(). If the map returns null (a mapping whose value is absent/empty), the upgrade cannot remap the original output to the new output, so an IllegalArgumentException naming the tag and expanded transform is thrown.

Solutions

  1. Check the expanded transform proto returned by the transform service for a complete outputsMap (key AND non-empty value)
  2. Fix or upgrade the transform service so it always fills in the new PCollection id for each output tag
  3. Validate the expansion response before applying replacements

Example fix

// before: outputsMap = {out1: ""}
// after: service returns outputsMap = {out1: "pcollection_1"}
Defensive patterns

Strategy: validation

Validate before calling

for (Map.Entry<String, String> e : originalTransform.getOutputsMap().entrySet()) {
  String newOutput = expandedTransform.getOutputsMap().get(e.getKey());
  if (newOutput == null || newOutput.isEmpty()) {
    throw new IllegalStateException("Missing replacement output for tag " + e.getKey());
  }
}

Try / catch

try {
  upgrader.upgradeTransformsViaTransformService(pipeline, ids, service);
} catch (IllegalArgumentException e) {
  // handle null replacement output from expansion service
}

Prevention

When it happens

Trigger: Calling upgradeTransformsViaTransformService when the expanded transform's outputsMap contains the original tag as a key but the value (new PCollection id) is null or missing.

Common situations: Malformed response from the transform/expansion service; proto field cleared during serialization; service bug producing incomplete outputsMap values.

Related errors


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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/TransformUpgrader.java:318

    // We record transforms that consume outputs of the old transform and update them to consume
    // outputs of the new (upgraded) transform.
    Collection<String> oldOutputs = transformToUpgrade.getOutputsMap().values();
    Map<String, String> inputReplacements = new HashMap<>();
    if (transformToUpgrade.getOutputsMap().size() == 1) {
      inputReplacements.put(
          oldOutputs.iterator().next(),
          expandedTransform.getOutputsMap().values().iterator().next());
    } else {
      for (Map.Entry<String, String> entry : transformToUpgrade.getOutputsMap().entrySet()) {
        if (!expandedTransform.getOutputsMap().keySet().contains(entry.getKey())) {
          throw new IllegalArgumentException(
              "Original transform had an output with tag "
                  + entry.getKey()
                  + " but upgraded transform did not.");
        }
        String newOutput = expandedTransform.getOutputsMap().get(entry.getKey());
        if (newOutput == null) {
          throw new IllegalArgumentException(
              "Could not find an output with tag "
                  + entry.getKey()
                  + " for the transform "
                  + expandedTransform);
        }
        inputReplacements.put(entry.getValue(), newOutput);
      }
    }

    // The list of obsolete (overridden) transforms that should be removed from the pipeline
    // produced by this method.
    List<String> transformsToRemove = new ArrayList<>();
    recursivelyFindSubTransforms(
        transformId, runnerAPIpipeline.getComponents(), transformsToRemove);

    Map<String, RunnerApi.PTransform> updatedExpandedTransformMap =
        expandedComponents.getTransformsMap().entrySet().stream()
            .filter(

View on GitHub (pinned to 12126d8942)