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

  1. Create a fresh visitor (Defaults subclass) for each traversal instead of reusing one.
  2. Do not invoke visitor methods after Pipeline.run()/traverseTopologically returns; capture needed values during traversal.
  3. If you need post-traversal access, hold a reference to the Pipeline object itself, not via the visitor.
  4. 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

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


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