apache/beam · warning

Exceptions are thrown from DoFn.teardown method when trying…

Error message

Exceptions are thrown from DoFn.teardown method when trying to discard ProcessBundleHandler

What it means

When a ProcessBundleHandler is discarded, all registered DoFn teardown functions are run in reverse order; OutOfMemoryError is rethrown, but any other Throwable from teardown is caught and this warning is logged. The bundle handler continues discarding (metrics are discarded), but user cleanup logic partially failed.

Solutions

  1. Fix the exception in the logged stack trace inside your @Teardown method.
  2. Make teardown idempotent and null-safe (check fields before use).
  3. Do not throw from teardown; log and swallow recoverable cleanup errors in user code.
  4. Release external resources in FinishBundle rather than relying solely on teardown.

Example fix

// before
@Teardown
public void teardown() {
  connection.close(); // throws if never opened
}
// after
@Teardown
public void teardown() {
  if (connection != null) {
    try { connection.close(); } catch (Exception e) { LOG.warn("close failed", e); }
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard teardown state
if (connection != null && !connection.isClosed()) { /* safe to close */ }

Try / catch

try {
  teardown();
} catch (Exception e) {
  LOG.warn("teardown failed", e); // never propagate from @Teardown
}

Prevention

When it happens

Trigger: One or more DoFn.teardown() methods (via @Teardown annotated methods) throw an exception when the handler is discarded at the end of processing; only OutOfMemoryError propagates.

Common situations: Teardown closing connections that are already closed; NPEs from uninitialized fields in teardown; external resource cleanup failures during harness shutdown or invalid bundle retries.

Related errors


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

Appendix: source

Thrown at sdks/java/harness/src/main/java/org/apache/beam/fn/harness/control/ProcessBundleHandler.java:1205

      getProgressRequestLock().unlock();
    }

    void discard() {
      synchronized (this) {
        this.instructionId = null;
        this.cacheTokens = null;
        if (this.bundleCache != null) {
          this.bundleCache.clear();
        }
        // setupFunctions are invoked in createBundleProcessor. Invoke teardownFunction here as the
        // BundleProcessor is already removed from cache and won't be re-used.
        for (ThrowingRunnable teardownFunction : Lists.reverse(this.getTearDownFunctions())) {
          try {
            teardownFunction.run();
          } catch (OutOfMemoryError oom) {
            throw oom;
          } catch (Throwable e) {
            LOG.warn(
                "Exceptions are thrown from DoFn.teardown method when trying to discard "
                    + "ProcessBundleHandler",
                e);
          }
        }
        getMetricsEnvironmentStateForBundle().discard();
        for (BeamFnDataOutboundAggregator aggregator : getOutboundAggregators().values()) {
          aggregator.discard();
        }
      }
    }

    // this is called in cachedBundleProcessors removal listener
    void shutdown() {
      for (ThrowingRunnable tearDownFunction : getTearDownFunctions()) {
        LOG.debug("Tearing down function {}", tearDownFunction);
        try {
          tearDownFunction.run();

View on GitHub (pinned to 12126d8942)