karatelabs/karate · error · RuntimeException
waitForOutput timed out after ms
Error message
waitForOutput timed out after ms
What it means
waitForOutput(predicate, timeout) registers a predicate over the process output and waits for a line/chunk matching it. If the deadline passes with no matching output, it removes the pending predicate/future and throws 'waitForOutput timed out after <n>ms'. It means the expected output never appeared in the process's stdout/stderr within the timeout.
Solutions
- Verify the exact expected text against the process's actual output (capture getStdOut()/getStdErr() after failure)
- Increase the timeout; first-run JIT/classpath startup on CI is much slower than locally
- Ensure the target output stream is captured - keep redirectErrorStream true (default) or attach a listener to stderr too
- Use readyLine() for readiness instead of ad-hoc substring matching, or loosen the predicate (case-insensitive/regex)
Example fix
// before
handle.waitForOutput("Server is ready", 5_000); // banner actually is "Listening on..."
// after
handle.waitForOutput("Listening on", 30_000); // or readyLine():
handle.readyLine(30_000); Defensive patterns
Strategy: try-catch
Validate before calling
if (timeoutMillis < expectedStartupUpperBoundMs) {
throw new IllegalArgumentException("waitForOutput timeout " + timeoutMillis + "ms below expected startup bound");
} Try / catch
try {
handle.waitForOutput("Started", 30_000);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("waitForOutput timed out")) {
log.error("process output so far: stdout={} stderr={}", handle.getStdOut(), handle.getStdErr());
handle.stop(5_000);
} else {
throw e;
}
} Prevention
- Capture getStdOut()/getStdErr() on failure to see what the process actually printed
- Keep redirectErrorStream true so stderr text is also matched
- Use readyLine() for readiness instead of ad-hoc substrings
- Set timeouts generously and fail fast on the surrounding test, not inside waitForOutput
- Assert the exact banner text against the process version you run
When it happens
Trigger: Calling waitForOutput("some text", timeoutMillis) (or the no-timeout overload's delegates, jsGet, readyLine) when the process never prints matching output - wrong expected string, slower startup than the timeout, or output going to a stream not captured (e.g. with redirectErrorStream false and text on stderr).
Common situations: Waiting for a server 'started' banner that changed across versions, matching against stderr while only stdout is wired to listeners, fixed timeouts too small for cold CI runners, or typos/case mismatches in the expected substring.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- process timed out after ms
- timeout waiting for element
- timeout waiting for any element
- timeout waiting for text
- timeout waiting for element to be enabled
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/bfe02ca70be92ea8.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/process/ProcessHandle.java:402
*
* @param predicate Test function that receives the line
* @param timeoutMillis Timeout in milliseconds (0 = no timeout)
* @return The line that matched
*/
public String waitForOutput(Predicate<String> predicate, long timeoutMillis) {
CompletableFuture<String> future = new CompletableFuture<>();
waitPredicates.add(predicate);
waitFutures.put(predicate, future);
try {
if (timeoutMillis > 0) {
return future.get(timeoutMillis, TimeUnit.MILLISECONDS);
} else {
return future.get();
}
} catch (TimeoutException e) {
waitPredicates.remove(predicate);
waitFutures.remove(predicate);
throw new RuntimeException("waitForOutput timed out after " + timeoutMillis + "ms");
} catch (Exception e) {
waitPredicates.remove(predicate);
waitFutures.remove(predicate);
throw new RuntimeException("error in waitForOutput", e);
}
}
public String getStdOut() {
synchronized (stdoutBuffer) {
return stdoutBuffer.toString();
}
}
public String getStdErr() {
synchronized (stderrBuffer) {
return stderrBuffer.toString();
}
}View on GitHub (pinned to a22eb90246)