apache/beam · error · IllegalStateException
Error collections cannot be added after Error Handler is clo
Error message
Error collections cannot be added after Error Handler is closed
What it means
ErrorHandler.addErrorCollection throws IllegalStateException if you try to register an error PCollection after the handler has been closed. Once close() runs, the handler flattens its error collections into the sink output, so late additions would be silently dropped — Beam forbids them.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/errorhandling/ErrorHandler.java:122
public PTransformErrorHandler(
PTransform<PCollection<ErrorT>, OutputT> sinkTransform,
Pipeline pipeline,
Coder<ErrorT> coder) {
this.sinkTransform = sinkTransform;
this.pipeline = pipeline;
this.coder = coder;
}
private void readObject(ObjectInputStream aInputStream)
throws ClassNotFoundException, IOException {
aInputStream.defaultReadObject();
errorCollections = new ArrayList<>();
}
@Override
public void addErrorCollection(PCollection<ErrorT> errorCollection) {
if (isClosed()) {
throw new IllegalStateException(
"Error collections cannot be added after Error Handler is closed");
}
errorCollections.add(errorCollection);
}
@Override
public boolean isClosed() {
return closed;
}
@Override
public @Nullable OutputT getOutput() {
if (!this.isClosed()) {
throw new IllegalStateException(
"ErrorHandler must be finalized before the output can be returned");
}
return sinkOutput;
}View on GitHub (pinned to 12126d8942)
Solutions
- Register all error PCollections before calling close().
- Restructure so the handler is closed only after pipeline construction is complete.
- Check isClosed() before adding, or add all collections in the same scope that builds the pipeline.
Example fix
// before handler.close(); handler.addErrorCollection(errorPcoll); // IllegalStateException // after handler.addErrorCollection(errorPcoll); handler.close();
Defensive patterns
Strategy: type-guard
Validate before calling
if (!errorHandler.isClosed()) { errorHandler.addErrorCollection(errorPcoll); } Type guard
boolean canAdd(ErrorHandler<?> h) {
try { return !h.isClosed(); } catch (IllegalStateException e) { return false; }
} Try / catch
try {
errorHandler.addErrorCollection(errorPcoll);
} catch (IllegalStateException e) {
throw new IllegalStateException("Register error collections before closing the handler", e);
} Prevention
- Register all error PCollections during pipeline construction only
- Close the handler in try-with-resources after registration is complete
- Keep handler add/close calls in one scope
When it happens
Trigger: Calling errorHandler.addErrorCollection(pcollection) after errorHandler.close() has been invoked — typically when application code finalizes the handler (e.g. in a finally block or via try-with-resources __exit__) before all error PCollections from transforms have been registered.
Common situations: Using the handler in try-with-resources while building the pipeline afterwards; closing the handler in one method and adding collections in another; restructuring pipeline-building code so close() happens earlier than intended.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- ErrorHandler must be finalized before the output can be retu
- Error handler is already closed, and may not be closed twice
- Expected state to be PENDING or STARTED, but was COMPLETE_SU
- Expected state to be PENDING or STARTED, but was COMPLETE_ER
- Expected state to be STARTED, but was PENDING
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/748dbf55a3e9dea5.
Report an issue: GitHub.