apache/beam · error · IllegalStateException
One or more ErrorHandlers aren't closed, and this pipeline c
Error message
One or more ErrorHandlers aren't closed, and this pipeline cannot be run. See the ErrorHandler documentation for expected usage
What it means
Before running, Pipeline.validateErrorHandlers() verifies that every ErrorHandler registered on the pipeline has been closed. An unclosed handler means error output (e.g. a write sink attached to bad-record routing) was never finalized, so run() throws this IllegalStateException to prevent silently dropping error records.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/Pipeline.java:737
public String apply(@Nonnull final Map.Entry<String, Collection<PTransform<?, ?>>> input) {
return input.getKey();
}
}
private static class IsUnique<K, V> implements Predicate<Map.Entry<K, Collection<V>>> {
@SuppressFBWarnings(
value = "NP_METHOD_PARAMETER_TIGHTENS_ANNOTATION",
justification = "https://github.com/google/guava/issues/920")
@Override
public boolean apply(@Nonnull final Map.Entry<K, Collection<V>> input) {
return input != null && input.getValue().size() == 1;
}
}
private void validateErrorHandlers() {
for (ErrorHandler<?, ?> errorHandler : errorHandlers) {
if (!errorHandler.isClosed()) {
throw new IllegalStateException(
"One or more ErrorHandlers aren't closed, and this pipeline "
+ "cannot be run. See the ErrorHandler documentation for expected usage");
}
}
}
}
View on GitHub (pinned to 12126d8942)
Solutions
- Call close() on every registered ErrorHandler after attaching its sink and before pipeline.run().
- Use try/finally around pipeline construction so close() runs even if intermediate steps throw.
- If the handler is genuinely unused, remove its registration from the pipeline instead of leaving it open.
- Review the ErrorHandler Javadoc usage pattern: create, wire into transforms, close, then run.
Example fix
// before // ErrorHandler<PCollectionTuple, ? > h = pipeline.registerErrorHandler(...); pipeline.run(); // throws // after // ErrorHandler<PFileSystem, ? > h = pipeline.registerErrorHandler(...); ... h.close(); pipeline.run();
Defensive patterns
Strategy: try-catch
Validate before calling
// Java: verify all handlers are closed before run
for (ErrorHandler<?, ?> h : registeredHandlers) {
if (!h.isClosed()) throw new IllegalStateException("Handler not closed: " + h);
} Try / catch
ErrorHandler<...> h = pipeline.registerErrorHandler(...);
try {
// wire transforms using h
h.close();
pipeline.run();
} catch (IllegalStateException e) {
if (e.getMessage().contains("ErrorHandlers aren't closed")) {
h.close();
pipeline.run(); // retry once closed
} else { throw e; }
} Prevention
- Adopt the create -> wire -> close -> run pattern from the ErrorHandler Javadoc
- Wrap pipeline construction in try/finally ensuring close()
- Grep for registerErrorHandler call sites and pair each with close()
When it happens
Trigger: Calling pipeline.run() while an ErrorHandler obtained via pipeline.registerErrorHandler(...) / construction is still open — i.e. the user never called errorHandler.close() (which attaches the error-collection sink) after wiring transforms.
Common situations: Using error handlers for write failures (e.g. BigQuery/Nio bad-record routing) and forgetting the close() step; early returns or exceptions in pipeline-construction code that skip the close call.
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
- Illegal access to pipeline after visitor traversal was compl
- Pipeline update will not be possible because the following t
- Failed to validate %s
- Failed to validate %s
- Failed to validate transform %s
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/7a4715bdc7a94aec.
Report an issue: GitHub.