karatelabs/karate · warning
Driver failed liveness probe on release, discarding instead…
Error message
Driver failed liveness probe on release, discarding instead of returning to pool
What it means
When a driver is released back to the pool, the provider probes its liveness with driver.isResponsive(). A driver that fails the probe is closed instead of pooled, so the next borrower does not get a dead channel. This is defensive insurance against CDP channels that died mid-scenario.
Solutions
- None needed for correct operation — the pool self-heals by closing and decrementing createdCount
- If frequent, investigate why browsers die (memory limits, headless crashes, stale chrome processes)
- Enable debug logging to correlate probe failures with scenario activity
Defensive patterns
Strategy: fallback
Validate before calling
// discard is automatic; validate driver health yourself before asserting
driver.waitUntilReady();
if (!driver.isResponsive()) { /* request a fresh driver */ } Type guard
boolean driverUsable = d -> !d.isTerminated() && d.isResponsive();
Prevention
- Keep browser memory in bounds to avoid renderer crashes
- Restart the browser process between large suites
- Treat 'failed liveness probe' warnings as a signal of browser instability, not a test failure
When it happens
Trigger: Releasing a driver whose websocket/CDP channel died (browser crash, renderer hang) so isResponsive() returns false during release().
Common situations: Chrome renderer crash during a long scenario; browser killed by OOM killer; driver object released after a CDP timeout already hinted the channel was sick.
Related errors
- Driver failed post-reset liveness probe, will discard
- Error resetting driver state, will discard
- Error closing driver
- browser did not return a browserContextId
- browser did not return a targetId for context
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/9631aa1212d70169.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/driver/PooledDriverProvider.java:256
logger.debug("Not returning terminated driver to pool");
createdCount.decrementAndGet();
return;
}
// Eagerly discard a driver whose channel went sick mid-scenario instead of
// returning it to the pool. The acquire-time resetDriver() probe would catch
// it eventually, but only AFTER the next scenario inherits the poisoned driver
// and eats its own timeout — which is how a single renderer stall under a slow
// CI container ("CDP timeout for: Page.captureScreenshot") cascaded into a batch
// of failures on the same pooled driver. Probing here (cheap, bounded — see
// isResponsive()) caps that cross-scenario contagion. We probe BEFORE
// cleanScenarioState() so a dead channel can't hang the stopIntercept/onDialog
// teardown calls on the full CDP timeout. Note: an eval-based probe can still
// pass on a renderer stalled only on compositor/paint work (the screenshot path),
// so this is insurance, not a guarantee — the bounded failureScreenshot timeout
// covers that case.
if (!driver.isResponsive()) {
logger.warn("Driver failed liveness probe on release, discarding instead of returning to pool");
closeDriverQuietly(driver);
createdCount.decrementAndGet();
return;
}
// Tear down scenario-scoped state BEFORE returning to the pool. This is the
// "top-level scenario exit" hook per DRIVER.md — the owner scenario is done,
// so any driver state it installed (intercept handler, dialog handler, etc.)
// belongs to a scope that no longer exists and must not leak into the next
// scenario that acquires this driver.
//
// Why this matters (context for future maintainers): intercept.feature's
// wildcard-pattern scenario set Fetch.enable via driver.intercept() and never
// called stopIntercept. The driver went back to the pool with Fetch.enable
// still active and a stale JS InterceptHandler from a destroyed scenario.
// Every subsequent Page.navigate on that driver paused ALL subresource
// requests through our onRequestPaused event handler, which runs synchronously
// on the CDP websocket dispatch thread. A heavy page (HTML + CSS + JS + etc)View on GitHub (pinned to a22eb90246)