apache/beam · error · IllegalStateException
Illegal access to pipeline after visitor traversal was compl
Error message
Illegal access to pipeline after visitor traversal was completed
What it means
In Java Beam's Pipeline.Defaults visitor, getPipeline() returns the pipeline captured at the start of traversal. After traversal completes, Defaults clears the reference; any visitor callback (checkForMatches, enterCompositeTransform, visitPrimitiveTransform) invoked afterwards throws this IllegalStateException to prevent mutating a pipeline during/after an already-completed traversal.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/Pipeline.java:429
* Control enum for indicating whether or not a traversal should process the contents of a
* composite transform or not.
*/
enum CompositeBehavior {
ENTER_TRANSFORM,
DO_NOT_ENTER_TRANSFORM
}
/**
* Default no-op {@link PipelineVisitor} that enters all composite transforms. User
* implementations can override just those methods they are interested in.
*/
class Defaults implements PipelineVisitor {
private @Nullable Pipeline pipeline;
protected Pipeline getPipeline() {
if (pipeline == null) {
throw new IllegalStateException(
"Illegal access to pipeline after visitor traversal was completed");
}
return pipeline;
}
@Override
public void enterPipeline(Pipeline pipeline) {
this.pipeline = checkNotNull(pipeline);
}
@Override
public CompositeBehavior enterCompositeTransform(TransformHierarchy.Node node) {
return CompositeBehavior.ENTER_TRANSFORM;
}
@Override
public void leaveCompositeTransform(TransformHierarchy.Node node) {}
View on GitHub (pinned to 12126d8942)
Solutions
- Create a fresh visitor (Defaults subclass) for each traversal instead of reusing one.
- Do not invoke visitor methods after Pipeline.run()/traverseTopologically returns; capture needed values during traversal.
- If you need post-traversal access, hold a reference to the Pipeline object itself, not via the visitor.
- Refactor custom checks to run inside the visit callbacks, not after.
Example fix
// before // Defaults v = new MyVisitor(); pipeline.traverseTopologically(v); pipeline.run(); v.enterCompositeTransform(node); // throws // after // MyVisitor v = new MyVisitor(); pipeline.traverseTopologically(v); // do all inspection inside v's callbacks, before run()
Defensive patterns
Strategy: try-catch
Validate before calling
// Java: verify the visitor has not been consumed before reusing
if (visitorUsedOnce) {
throw new IllegalStateException('Create a fresh visitor per traversal');
} Try / catch
try {
pipeline.traverseTopologically(visitor);
} catch (IllegalStateException e) {
if (e.getMessage().contains("after visitor traversal was completed")) {
// recreate visitor and re-traverse
visitor = new MyVisitor();
pipeline.traverseTopologically(visitor);
} else { throw e; }
} Prevention
- Instantiate a new visitor for every traversal
- Never call visitor callbacks after Pipeline.run() or traverseTopologically returns
- Capture pipeline references directly, not through visitor state
When it happens
Trigger: Calling Pipeline.traverseTopologically(visitor) a second time with the same Defaults-derived visitor, or invoking visitor callbacks (e.g. a retained visitPrimitiveTransform) after run()/traversal finished.
Common situations: Custom PTransform validation tools that reuse a visitor instance across traversals; code that stores the visitor and touches the pipeline after Pipeline.run(); running validate() twice with a stateful visitor.
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
- Pipeline update will not be possible because the following t
- One or more ErrorHandlers aren't closed, and this pipeline c
- Failed to validate transform %s
- Unhandled input type ${input.getClass()}
- Cannot access StartBundleContext outside of @StartBundle met
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/12886afd36e0bbba.
Report an issue: GitHub.