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

  1. None needed for correct operation — the pool self-heals by closing and decrementing createdCount
  2. If frequent, investigate why browsers die (memory limits, headless crashes, stale chrome processes)
  3. 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

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


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)