karatelabs/karate · warning
ext onShutdown failed
Error message
ext onShutdown failed ({}): {} What it means
Karate 'ext' boot extensions can register an onShutdown callback invoked when the Suite finishes. Each callback is best-effort: if one throws, Karate logs this warning naming the extension class and the exception message, then keeps going (the ext's JSONL listener registration is still removed). Suite results are unaffected.
Solutions
- Fix the Ext.onShutdown() implementation named in the log to be idempotent and exception-safe
- Wrap external cleanup in the extension with its own try/catch and meaningful logging
- Make sure onShutdown only releases resources the extension itself created
- If the extension is third-party, update it or remove it from the boot binding if not needed
Example fix
// before
@Override public void onShutdown() { client.close(); files.flush(); }
// after
@Override public void onShutdown() {
try (client) { files.flushQuietly(); }
catch (Exception e) { logger.warn("ext cleanup failed", e); }
} Defensive patterns
Strategy: try-catch
Validate before calling
// in your Ext: make shutdown idempotent and testable before wiring into boot binding
@Override public void onShutdown() {
if (closed.getAndSet(true)) return;
try { doCleanup(); } catch (Exception e) { logger.warn("cleanup failed", e); }
} Try / catch
try { ext.onShutdown(); }
catch (Exception e) { logger.warn("ext onShutdown failed: {}", e.getMessage()); } // mirror Karate's own best-effort handling in the Ext Prevention
- Write Ext.onShutdown() to be idempotent (guard with a closed flag)
- Never let shutdown-time network or remote calls throw out of onShutdown
- Only release resources the extension created; don't close shared/global resources
- Log the real exception inside the extension instead of relying on e.getMessage() alone
When it happens
Trigger: Suite.run() teardown iterating bootBinding.getExts() where ext.onShutdown() throws — e.g. a custom Ext whose onShutdown closes resources that are already closed, performs network cleanup that fails, or has a bug.
Common situations: Custom plugin/extension closing an HTTP client or DB pool twice; extension trying to flush data to a service that is unreachable at teardown; exceptions inside user-provided shutdown hooks.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- setTimeout: karate is shutting down
- registered while , stopping immediately
- shutdown in progress failed
- no time left to stop
- timed out stopping after ms
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/df328b211d08d957.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/core/Suite.java:613
}
// Close JSONL event writer
if (jsonlWriter != null) {
try {
removeJsonlListener(jsonlWriter);
jsonlWriter.close();
} catch (Exception e) {
logger.warn("Failed to close JSONL event stream: {}", e.getMessage());
}
}
// Ext onShutdown — best-effort; exceptions are logged + dropped per K43.
if (bootBinding != null) {
for (Ext ext : bootBinding.getExts()) {
try {
ext.onShutdown();
} catch (Exception e) {
logger.warn("ext onShutdown failed ({}): {}",
ext.getClass().getName(), e.getMessage());
}
removeJsonlListener(ext);
}
}
// Notify listeners
for (ResultListener listener : resultListeners) {
listener.onSuiteEnd(result);
}
}
return result;
}
// Thread-safe listener management for JSONL writer
private final List<RunListener> mutableListeners = new ArrayList<>();
View on GitHub (pinned to a22eb90246)