apache/beam · error · UnsupportedOperationException
Unknown output type
Error message
Unknown output type: ${output.getClass()} What it means
extractOutputs expands a custom PTransform output's expand() map and hit an entry whose value is not a PCollection (the unsupported branch for arbitrary PValue outputs). The output object (and its non-PCollection expand value under the reported key) is the input at fault: the expansion service can only wire PCollection outputs back into its response.
Solutions
- Ensure the transform always returns a non-null PCollection or POutput.
- Check the implementation for early-return/null paths on empty input.
- Wrap the transform to produce a standard PCollection output.
- Inspect output.getClass() in the message and handle that type upstream.
Example fix
// before return condition ? transform.expand(input) : null; // after PCollection<T> result = transform.expand(input); return requireNonNull(result, "transform output must not be null");
Defensive patterns
Strategy: validation
Validate before calling
if (output == null) throw new IllegalStateException("Transform produced no output");
if (!(output instanceof PCollection) && !(output instanceof POutput)) throw new IllegalStateException("Unsupported output type: " + output.getClass()); Type guard
boolean hasExtractableOutput(Object out) { return out instanceof PCollection || out instanceof POutput; } Try / catch
try { Map<String, PCollection<?>> outs = provider.extractOutputs(output); } catch (UnsupportedOperationException e) { log.error("No extractable output: {}", e.getMessage()); throw new TransformContractException(e); } Prevention
- Never return null from PTransform.expand/apply
- Unit-test that transforms produce outputs for representative inputs
- Restrict the expansion service to transforms with standard outputs
- Emit empty PCollections for empty-input cases
When it happens
Trigger: A transform's apply/expand returns null output; or returns a type not covered by the PCollection/POutput branches in extractOutputs.
Common situations: Custom transforms returning null on failure; third-party PTransform wrappers with nonstandard output types.
Related errors
- Unable to parse the output type
- Unable to perform expansion for transform
- A dataSourceConfiguration or dataSourceProviderFn has…
- A list of URNs for overriding transforms was provided but…
- A cannot be expanded
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/89171ca8177a2642.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/TransformProvider.java:121
return indexToPCollection.build();
} else if (output != null) {
// This is needed to support custom output types.
Map<TupleTag<?>, PValue> values = output.expand();
Map<String, PCollection<?>> returnMap = new HashMap<>();
for (Map.Entry<TupleTag<?>, PValue> entry : values.entrySet()) {
if (!(entry.getValue() instanceof PCollection)) {
throw new UnsupportedOperationException(
"Unable to parse the output type "
+ output.getClass()
+ " due to key "
+ entry.getKey()
+ " not mapping to a PCollection");
}
returnMap.put(entry.getKey().getId(), (PCollection<?>) entry.getValue());
}
return returnMap;
} else {
throw new UnsupportedOperationException("Unknown output type: " + output.getClass());
}
}
default Map<String, PCollection<?>> apply(
Pipeline p, String name, RunnerApi.FunctionSpec spec, Map<String, PCollection<?>> inputs) {
return extractOutputs(
Pipeline.applyTransform(name, createInput(p, inputs), getTransform(spec, p.getOptions())));
}
default String getTransformUniqueID(RunnerApi.FunctionSpec spec) {
if (BeamUrns.getUrn(ExternalTransforms.ExpansionMethods.Enum.SCHEMA_TRANSFORM)
.equals(spec.getUrn())) {
ExternalTransforms.SchemaTransformPayload payload;
try {
payload = ExternalTransforms.SchemaTransformPayload.parseFrom(spec.getPayload());
if (PTransformTranslation.MANAGED_TRANSFORM_URN.equals(payload.getIdentifier())) {
try {
// ManagedSchemaTransform includes a schema field transform_identifier that includes theView on GitHub (pinned to 12126d8942)