{"record":{"id":"05062c58bc0c1d8a","repo":"apache/beam","slug":"a-pvalue-contained-in-partiallyexpanded-expanded-to-a-non","errorCode":null,"errorMessage":"A PValue contained in <partiallyExpanded> expanded to a non-PCollection: <value>","messagePattern":"A PValue contained in <partiallyExpanded> expanded to a non-PCollection: <value>","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/values/PValues.java","lineNumber":92,"sourceCode":"        if (pvalue.getValue().expand().size() == 1\n            && Iterables.getOnlyElement(pvalue.getValue().expand().values())\n                .equals(pvalue.getValue())) {\n          throw new IllegalStateException(\n              String.format(\n                  \"Non %s %s that expands into itself %s\",\n                  PCollection.class.getSimpleName(),\n                  PValue.class.getSimpleName(),\n                  pvalue.getValue()));\n        }\n        /* At this point we know it is a PCollectionView or some internal hacked PValue. To be\n        liberal, we\n        allow it to expand into any number of PCollections, but do not allow structures that\n        require\n        further recursion. */\n        for (Map.Entry<TupleTag<?>, PValue> valueComponent :\n            pvalue.getValue().expand().entrySet()) {\n          if (!(valueComponent.getValue() instanceof PCollection)) {\n            throw new IllegalStateException(\n                String.format(\n                    \"A %s contained in %s expanded to a non-%s: %s\",\n                    PValue.class.getSimpleName(),\n                    partiallyExpanded,\n                    PCollection.class.getSimpleName(),\n                    valueComponent.getValue()));\n          }\n          @Nullable PCollection<?> previous =\n              result.put(valueComponent.getKey(), (PCollection<?>) valueComponent.getValue());\n          if (previous != null) {\n            throw new IllegalArgumentException(\n                String.format(\n                    \"Found conflicting %ss in flattened expansion of %s: %s maps to %s and %s\",\n                    partiallyExpanded,\n                    TupleTag.class.getSimpleName(),\n                    valueComponent.getKey(),\n                    previous,\n                    valueComponent.getValue()));","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/values/PValues.java#L74-L110","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Flatten nested composites: have the outer transform expand through to the underlying PCollections.","Call PValues.expandedExplicitly/fullyExpand against the correct level, or expand the intermediate value first.","Refactor so transform outputs are PCollectionTuple / PCollectionList of concrete PCollections.","Only one level of nesting is supported — restructure deeper hierarchies in pipeline construction."],"exampleFix":"// before\nreturn PValues.expandValue(nestedCompositeOutput); // contains a non-PCollection PValue\n// after\nreturn PValues.expandValue(nestedCompositeOutput.get(PCollection.class)); // expand the wrapper first","handlingStrategy":"validation","validationCode":"for (PValue comp : value.expand().values()) {\n  for (PValue c2 : comp.expand().values()) {\n    if (!(c2 instanceof PCollection)) throw new IllegalStateException(\"expansion nested >1 level\");\n  }\n}","typeGuard":"static boolean fullyExpandedToPCollections(PValue v) {\n  return v.expand().values().stream().allMatch(x -> x instanceof PCollection);\n}","tryCatchPattern":"try {\n  expanded = PValues.expandInput(value);\n} catch (IllegalStateException e) {\n  // expand the intermediate wrapper PValue first, then retry\n}","preventionTips":["Keep composite transforms to a single expansion level of PCollections.","Return PCollectionTuple/PCollectionList from nested composites.","Expand intermediate values before passing them to APIs that call fullyExpand."],"tags":["java","apache-beam","pvalue-expansion","illegal-state","nesting"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}