apache/beam · error · IllegalStateException

%s with no %s or %s

Error message

%s with no %s or %s

What it means

Thrown by OutputDeduplicator.ensureSingleProducer when a StageOrTransform entry in the deduplication targets is neither an ExecutableStage nor a PTransformNode. The deduplicator only knows how to process those two payload types; anything else indicates an internal invariant violation in how the dedup targets were collected.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/graph/OutputDeduplicator.java:121

      } else if (deduplicationTargets.getKey().getTransform() != null) {
        PTransformDeduplication deduplication =
            deduplicatePCollections(
                deduplicationTargets.getKey().getTransform(),
                deduplicationTargets.getValue(),
                unzippedComponents::containsPcollections);
        for (Entry<String, PipelineNode.PCollectionNode> originalToPartialReplacement :
            deduplication.getOriginalToPartialPCollections().entrySet()) {
          originalToPartial.put(
              originalToPartialReplacement.getKey(), originalToPartialReplacement.getValue());
          unzippedComponents.putPcollections(
              originalToPartialReplacement.getValue().getId(),
              originalToPartialReplacement.getValue().getPCollection());
        }
        updatedTransforms.put(
            deduplicationTargets.getKey().getTransform().getId(),
            deduplication.getUpdatedTransform());
      } else {
        throw new IllegalStateException(
            String.format(
                "%s with no %s or %s",
                StageOrTransform.class.getSimpleName(),
                ExecutableStage.class.getSimpleName(),
                PipelineNode.PTransformNode.class.getSimpleName()));
      }
    }

    Set<PipelineNode.PTransformNode> introducedFlattens = new LinkedHashSet<>();
    for (Map.Entry<String, Collection<PipelineNode.PCollectionNode>> partialFlattenTargets :
        originalToPartial.asMap().entrySet()) {
      String flattenId =
          SyntheticComponents.uniqueId("unzipped_flatten", unzippedComponents::containsTransforms);
      PTransform flattenPartialPCollections =
          createFlattenOfPartials(
              flattenId, partialFlattenTargets.getKey(), partialFlattenTargets.getValue());
      unzippedComponents.putTransforms(flattenId, flattenPartialPCollections);
      introducedFlattens.add(PipelineNode.pTransform(flattenId, flattenPartialPCollections));

View on GitHub (pinned to 12126d8942)

Solutions

  1. Ensure the ExecutableStage/PTransform graph fed to OutputDeduplicator was produced by the standard fusion pipeline (GreedyStageFuser).
  2. If a new node type exists, add a branch in ensureSingleProducer to handle it.
  3. Audit any custom graph-rewriting code that constructs StageOrTransform values.
  4. Capture the offending entry (getKey()) in a debugger to see the unexpected node type.

Example fix

// before: passing ad-hoc StageOrTransform.of(unknownNode)
// after: only feed fused output
DeduplicatedFlattenToPCollections out =
    OutputDeduplicator.ensureSingleProducer(executable, fusedStages, dedupTargets);
Defensive patterns

Strategy: validation

Validate before calling

for (Map.Entry<StageOrTransform, ?> e : deduplicationTargets.entrySet()) {
  if (!(e.getKey().getStage() instanceof ExecutableStage) && !(e.getKey().getTransform() instanceof PipelineNode.PTransformNode)) throw new IllegalStateException("Unexpected StageOrTransform payload");
}

Type guard

boolean isKnownStageOrTransform(StageOrTransform s) { return s.getStage() instanceof ExecutableStage || s.getTransform() instanceof PipelineNode.PTransformNode; }

Try / catch

try { result = OutputDeduplicator.ensureSingleProducer(executable, fusedStages, targets); } catch (IllegalStateException e) { log.error("Dedup target is neither ExecutableStage nor PTransformNode", e); throw e; }

Prevention

When it happens

Trigger: Running output deduplication (ensureSingleProducer) on a deduplicationTargets map whose StageOrTransform wraps a node type other than ExecutableStage or PTransformNode — a bug in graph construction or an unhandled node kind.

Common situations: Custom runner integrations building ExecutableStages by hand; new pipeline node types added without updating OutputDeduplicator; corrupted fusion results passed into deduplication.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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