apache/beam · error · IllegalArgumentException
Output coders were already specified
Error message
Output coders were already specified
What it means
withOutputCoders sets the map of output PCollection coders for the cross-language transform. The library throws IllegalArgumentException if output coders were already specified on this builder, since redefining the coder map would silently discard previously configured coders. Coders can only be set once per transform instance.
Source
Thrown at sdks/java/extensions/python/src/main/java/org/apache/beam/sdk/extensions/python/PythonExternalTransform.java:265
if (typeHints.containsKey(argType)) {
throw new IllegalArgumentException(
String.format("typehint for arg type %s already exists", argType));
}
typeHints.put(argType, fieldType);
return this;
}
/**
* Specifies the keys and {@link Coder}s of the output {@link PCollection}s produced by this
* transform.
*
* @param outputCoders a mapping from output keys to {@link Coder}s.
* @return updated wrapper for the cross-language transform.
*/
public PythonExternalTransform<InputT, OutputT> withOutputCoders(
Map<String, Coder<?>> outputCoders) {
if (this.outputCoders.size() > 0) {
throw new IllegalArgumentException("Output coders were already specified");
}
this.outputCoders.putAll(outputCoders);
return this;
}
/**
* Specifies the {@link Coder} of the output {@link PCollection}s produced by this transform.
* Should only be used if this transform produces a single output.
*
* @param outputCoder output {@link Coder} of the transform.
* @return updated wrapper for the cross-language transform.
*/
public PythonExternalTransform<InputT, OutputT> withOutputCoder(Coder<?> outputCoder) {
if (this.outputCoders.size() > 0) {
throw new IllegalArgumentException("Output coders were already specified");
}
// Output key should not matter when only specifying a single output.View on GitHub (pinned to 12126d8942)
Solutions
- Remove the duplicate coder-setting call and keep a single withOutputCoders invocation
- Combine all coders into one map and pass it in a single call
- Build a fresh PythonExternalTransform if you need a different coder configuration
Example fix
// before ext.withOutputCoder(myCoder).withOutputCoders(coderMap); // throws // after ext.withOutputCoders(coderMap); // single specification
Defensive patterns
Strategy: validation
Validate before calling
if (outputCoders != null && !outputCoders.isEmpty()) {
throw new IllegalStateException("output coders already set");
}
transform.withOutputCoders(outputCoders); Try / catch
try {
transform.withOutputCoders(map);
} catch (IllegalArgumentException e) {
// coders already set; reuse existing configuration
} Prevention
- Call withOutputCoders or withOutputCoder exactly once, never both
- Build the full coder map first, then set it in a single call
- Treat PythonExternalTransform builders as single-use
When it happens
Trigger: Calling withOutputCoders(Map) when this.outputCoders is non-empty — i.e. after a prior withOutputCoders or withOutputCoder call on the same PythonExternalTransform.
Common situations: Chaining both withOutputCoder(...) and withOutputCoders(...); calling withOutputCoders twice in a fluent chain; reusing a pre-configured transform object in two pipelines.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- cannot encode a null Byte
- cannot estimate size for unsupported null value
- NonDeterministicException(target, message, e)
- Unable to encode element '" + value + "' with coder '" + thi
- Unable to provide coder for %s, this factory can only provid
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/c4988c839862aefd.
Report an issue: GitHub.