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

  1. Register all error PCollections before calling close().
  2. Restructure so the handler is closed only after pipeline construction is complete.
  3. 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

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/748dbf55a3e9dea5. Report an issue: GitHub.