apache/beam · error · java.lang.IllegalStateException

A PValue contained in

Error message

A PValue contained in <partiallyExpanded> expanded to a non-PCollection: <value>

What it means

When fully expanding a PValue, Beam allows one level of expansion: each contained PValue must expand to PCollections only. If a nested component expands to another non-PCollection PValue, recursion would be required (which fullyExpand does not perform), so it throws IllegalStateException.

Solutions

  1. Flatten nested composites: have the outer transform expand through to the underlying PCollections.
  2. Call PValues.expandedExplicitly/fullyExpand against the correct level, or expand the intermediate value first.
  3. Refactor so transform outputs are PCollectionTuple / PCollectionList of concrete PCollections.
  4. Only one level of nesting is supported — restructure deeper hierarchies in pipeline construction.

Example fix

// before
return PValues.expandValue(nestedCompositeOutput); // contains a non-PCollection PValue
// after
return PValues.expandValue(nestedCompositeOutput.get(PCollection.class)); // expand the wrapper first
Defensive patterns

Strategy: validation

Validate before calling

for (PValue comp : value.expand().values()) {
  for (PValue c2 : comp.expand().values()) {
    if (!(c2 instanceof PCollection)) throw new IllegalStateException("expansion nested >1 level");
  }
}

Type guard

static boolean fullyExpandedToPCollections(PValue v) {
  return v.expand().values().stream().allMatch(x -> x instanceof PCollection);
}

Try / catch

try {
  expanded = PValues.expandInput(value);
} catch (IllegalStateException e) {
  // expand the intermediate wrapper PValue first, then retry
}

Prevention

When it happens

Trigger: Nesting composite PTransform outputs more than one level deep (a PValue whose expand() contains another non-PCollection PValue) and passing it to expandOutput/expandInput/expandValue.

Common situations: A composite transform returning another composite's raw output PValue instead of its expanded PCollections; hand-built nested PValue graphs in custom IO or test harness code.

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/05062c58bc0c1d8a. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/values/PValues.java:92

        if (pvalue.getValue().expand().size() == 1
            && Iterables.getOnlyElement(pvalue.getValue().expand().values())
                .equals(pvalue.getValue())) {
          throw new IllegalStateException(
              String.format(
                  "Non %s %s that expands into itself %s",
                  PCollection.class.getSimpleName(),
                  PValue.class.getSimpleName(),
                  pvalue.getValue()));
        }
        /* At this point we know it is a PCollectionView or some internal hacked PValue. To be
        liberal, we
        allow it to expand into any number of PCollections, but do not allow structures that
        require
        further recursion. */
        for (Map.Entry<TupleTag<?>, PValue> valueComponent :
            pvalue.getValue().expand().entrySet()) {
          if (!(valueComponent.getValue() instanceof PCollection)) {
            throw new IllegalStateException(
                String.format(
                    "A %s contained in %s expanded to a non-%s: %s",
                    PValue.class.getSimpleName(),
                    partiallyExpanded,
                    PCollection.class.getSimpleName(),
                    valueComponent.getValue()));
          }
          @Nullable PCollection<?> previous =
              result.put(valueComponent.getKey(), (PCollection<?>) valueComponent.getValue());
          if (previous != null) {
            throw new IllegalArgumentException(
                String.format(
                    "Found conflicting %ss in flattened expansion of %s: %s maps to %s and %s",
                    partiallyExpanded,
                    TupleTag.class.getSimpleName(),
                    valueComponent.getKey(),
                    previous,
                    valueComponent.getValue()));

View on GitHub (pinned to 12126d8942)