apache/beam · error · AbandonedNodeException

The pipeline contains abandoned PAssert(s).

Error message

The pipeline contains abandoned PAssert(s).

What it means

After a run, TestPipeline compares pipeline graph nodes against nodes actually visited during execution. If PAssert nodes exist that were never visited by the run, it throws AbandonedNodeException with this message — meaning some assertions were attached but never evaluated.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/testing/TestPipeline.java:237

        return; // this method is to protect against spurious success, so failure is fine
      }

      final List<TransformHierarchy.Node> runVisitedNodes =
          checkStateNotNull(
              this.runVisitedNodes,
              "Internal error: non-empty pipeline has been visited but still no runVisitedNodes");
      final List<TransformHierarchy.Node> pipelineNodes = recordPipelineNodes(pipeline);
      if (runVisitedNodes.equals(pipelineNodes)) {
        return;
      }

      final boolean hasDanglingPAssert =
          pipelineNodes.stream()
              .filter(Predicates.not(Predicates.in(runVisitedNodes)))
              .anyMatch(isPAssertNode);

      if (hasDanglingPAssert) {
        throw new AbandonedNodeException("The pipeline contains abandoned PAssert(s).");
      } else {
        throw new AbandonedNodeException("The pipeline contains abandoned PTransform(s).");
      }
    }

    private boolean pipelineRunSucceeded() {
      return runVisitedNodes != null;
    }

    @Override
    protected void afterPipelineExecution() {
      runVisitedNodes = recordPipelineNodes(pipeline);
      super.afterPipelineExecution();
    }

    @Override
    protected void afterUserCodeFinished() {
      super.afterUserCodeFinished();

View on GitHub (pinned to 12126d8942)

Solutions

  1. Add all PAssert.that(...) calls before invoking pipeline.run().
  2. Verify the PAssert is attached to a PCollection that is part of the executed pipeline (not a detached/unused output).
  3. Re-run the pipeline after adding new assertions.

Example fix

// before
pipeline.run().waitUntilFinish();
PAssert.that(pcoll).containsInAnyOrder("x");
// after
PAssert.that(pcoll).containsInAnyOrder("x");
pipeline.run().waitUntilFinish();
Defensive patterns

Strategy: validation

Validate before calling

boolean allAssertsBeforeRun = assertsAddedAt < runCalledAt; // enforce asserts precede run()

Try / catch

try { pipeline.run().waitUntilFinish(); } catch (AbandonedNodeException e) { fail("Attach PAsserts before run(): " + e.getMessage()); }

Prevention

When it happens

Trigger: PAsserts added to the pipeline after run() was called, or PAsserts applied to a side branch that the runner never executed/visited, with runVisitedNodes not containing them.

Common situations: Conditionally adding assertions after run(); attaching PAsserts to outputs of transforms pruned by the runner; building a second pipeline object and asserting on it while running another.

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/4c4a9dc9a8d4829e. Report an issue: GitHub.