karatelabs/karate · error · RuntimeException

listen timed out after

Error message

listen timed out after <timeoutMs>ms

What it means

The `listen` keyword pauses the scenario until external code (e.g. a mock server or browser callback) supplies a result via listenResult. If nothing arrives within the configured timeout, the CountDownLatch await expires and the runtime throws "listen timed out after <timeoutMs>ms".

Solutions

  1. Verify the code paired with listen actually calls `karate.signal(result)` (or the listen server posts the result) and that it is running
  2. Increase the listen timeout, e.g. `* listen 30000 result` for slow environments
  3. Check ports/firewalls and callback URLs so the external side can reach the listener; add logging on the callback path

Example fix

// before
* listen 5000 token   // times out in slow CI
// after
* listen 60000 token
Defensive patterns

Strategy: try-catch

Try / catch

try { karate.listen(60000, 'token'); } catch (RuntimeException e) { if (e.getMessage().startsWith("listen timed out")) { /* check callback fired / increase timeout */ } throw e; }

Prevention

When it happens

Trigger: `* listen <timeout> someVariable` where no callback invokes karate.signal(listenKey) / sets the listen result before timeoutMs elapses.

Common situations: OAuth/browser redirect flows where the external service never calls back; mock server not started or listening on the wrong port; async JS in the browser not triggering the result; timeout too short for a slow environment.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/core/ScenarioRuntime.java:2482

    public void setListenResult(Object result) {
        this.listenResult = result;
        this.listenLatch.countDown();
    }

    /**
     * Wait for a signal with timeout.
     * Returns the signaled result or throws on timeout.
     */
    public Object waitForListenResult(long timeoutMs) {
        try {
            if (listenLatch.await(timeoutMs, TimeUnit.MILLISECONDS)) {
                Object result = listenResult;
                // Reset for potential reuse
                listenResult = null;
                listenLatch = new CountDownLatch(1);
                return result;
            }
            throw new RuntimeException("listen timed out after " + timeoutMs + "ms");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("listen interrupted", e);
        }
    }

    /**
     * Get the current listen result without waiting.
     */
    public Object getListenResult() {
        return listenResult;
    }

    // ========== Performance Testing (Gatling Integration) ==========

    /**
     * Check if performance mode is enabled.
     * When true, HTTP request timing is reported via PerfHook.

View on GitHub (pinned to a22eb90246)