karatelabs/karate · warning
executor did not terminate
Error message
executor did not terminate: {} What it means
KarateLifecycle.stop() shuts down its internal executor and calls awaitTermination(DRAIN_MILLIS). If the executor's threads still have not terminated after the drain window, shutdownNow() has already interrupted them and this warning logs that termination did not complete. Non-daemon worker threads may keep the JVM alive or tasks may be abandoned mid-run.
Solutions
- Ensure all registered Stoppables stop promptly (fix their stop() implementations)
- Investigate which task blocks the executor — take a thread dump at shutdown to identify the stuck thread
- Allow more drain time if work legitimately needs it
- Use daemon threads for pooled work so a non-terminated executor cannot keep the JVM alive
Example fix
// before: task blocks on socket read, ignores interrupt socket.getInputStream().read(); // after socket.setSoTimeout(1000); // read becomes interruptible, stop completes
Defensive patterns
Strategy: validation
Validate before calling
// verify executor health before shutdown
if (!executor.isTerminated()) { executor.shutdownNow(); }
Prevention
- Make pooled tasks interruptible (socket timeouts, interruptible locks)
- Use daemon threads for background work
- Avoid blocking I/O without timeouts in Stoppables
- Audit leaked threads with a shutdown thread dump
When it happens
Trigger: Executor tasks that ignore interruption or block on non-interruptible I/O/locks during shutdown; very short DRAIN_MILLIS relative to work in flight; a submitted stoppable task hung inside stop().
Common situations: Hung background servers during suite teardown; CI agents where the process lingers after tests; leaked threads from user code registered as Stoppables.
Related errors
- ext onShutdown failed
- no time left to stop
- registered while , stopping immediately
- setTimeout:
- setTimeout: karate is shutting down
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/ac41309e0c2e3b5b.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/common/KarateLifecycle.java:507
@Override
public String lifecycleKind() {
return kind;
}
@Override
public ExecutorService lifecycleExecutor() {
return executor;
}
@Override
public void stop() {
if (executor == null || executor.isTerminated()) {
return;
}
executor.shutdownNow();
try {
if (!executor.awaitTermination(DRAIN_MILLIS, TimeUnit.MILLISECONDS)) {
logger.warn("executor did not terminate: {}", name);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
public String toString() {
return name;
}
}
}
View on GitHub (pinned to a22eb90246)