karatelabs/karate · warning

shutdown in progress failed

Error message

shutdown in progress failed: {}

What it means

During `shutdownAll`, a component's shutdown task completed exceptionally (`ExecutionException` from the Future). The lifecycle logs this warning with the cause message, keeps whatever results were collected, and continues shutting down remaining components instead of aborting.

Solutions

  1. Inspect the logged cause to find which component's stop() failed and why
  2. Make the component's stop() idempotent and tolerant of already-closed resources
  3. Check for double-shutdown paths (component stopping itself and lifecycle stopping it)
  4. Fix the underlying resource state (e.g. don't attempt network close on a dead socket)

Example fix

// before
public void stop() { socket.close(); } // throws if already closed
// after
public void stop() { if (socket != null && !socket.isClosed()) socket.close(); }
Defensive patterns

Strategy: try-catch

Try / catch

public void stop() {
    try { closeResources(); }
    catch (Exception e) { log.debug("stop failed (already closed?)", e); } // keep stop idempotent
}

Prevention

When it happens

Trigger: Any registered stoppable whose `stop()` throws during `shutdownAll()` — e.g. closing a socket already closed by a peer, a JDBC driver failing to close a broken connection, an HTTP client throwing on shutdown.

Common situations: Peer already closed the connection so stop() fails idempotently-badly; stop() called twice; resource in a broken state after a test failure; stop() performing I/O on a dead resource.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/d4ca5e059369b222. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/common/KarateLifecycle.java:296

                results = new ArrayList<>();
            }
        }
        if (joinable != null) {
            return join(joinable);
        }
        return drain();
    }

    private static List<StopResult> join(CompletableFuture<List<StopResult>> other) {
        try {
            return other.get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            synchronized (LOCK) {
                return List.copyOf(results);
            }
        } catch (ExecutionException e) {
            logger.warn("shutdown in progress failed: {}", e.getCause() == null ? e : e.getCause().getMessage());
            synchronized (LOCK) {
                return List.copyOf(results);
            }
        }
    }

    private static List<StopResult> drain() {
        List<Stoppable> snapshot;
        synchronized (REGISTERED) {
            snapshot = new ArrayList<>(REGISTERED);
            REGISTERED.clear();
        }
        Collections.reverse(snapshot);
        if (!snapshot.isEmpty()) {
            logger.debug("stopping {} registered component(s)", snapshot.size());
        }
        SHUTDOWN_THREAD.set(true);
        try {

View on GitHub (pinned to a22eb90246)