karatelabs/karate · error · RuntimeException
process timed out after ms
Error message
process timed out after ms
What it means
The timed waitSync(timeoutMillis) waits for process exit within a deadline; if the process has not exited when the deadline passes, it throws 'process timed out after <n>ms' as a TimeoutException-driven RuntimeException. This is the deliberate timeout signal for runaway subprocesses.
Solutions
- Increase the timeout to match realistic process duration, especially on slower CI machines
- Fix the subprocess so it terminates (close stdin, send a stop signal, or kill it) instead of waiting indefinitely
- If the process is meant to be long-lived (server), don't waitSync - use waitForOutput/readyLine to wait for readiness, then stop it explicitly
- Check whether the process is blocked on stdin/stdout backpressure; consume or redirect its streams
Example fix
// before
handle.waitSync(5_000); // server process never exits -> timeout
// after
handle.waitForOutput("started", 30_000); // wait for readiness line
// ... run tests ...
handle.stop(10_000); // then terminate explicitly Defensive patterns
Strategy: retry
Validate before calling
long elapsed = System.currentTimeMillis() - startNanos;
if (expectedMaxRuntimeMs > 0 && elapsed > expectedMaxRuntimeMs) { /* warn early */ } Try / catch
try {
handle.waitSync(30_000);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("process timed out after")) {
handle.stop(5_000); // clean up the runaway process
} else {
throw e;
}
} Prevention
- Size timeouts for CI, not local machines (multiply local duration by 3-5x)
- Never waitSync long-lived server processes; use waitForOutput/readyLine for readiness
- Always stop() the handle in a finally block to avoid leaks after timeouts
- Make subprocesses non-interactive (close stdin, pass -y/--no-input flags)
When it happens
Trigger: Calling waitSync(timeoutMillis) (directly or via exec/jsGet) when the subprocess runs longer than the given timeout - e.g. a server that never stops, a hung CLI waiting for stdin, or an unreasonably small timeout value.
Common situations: Forking a dev server for integration tests that keeps running instead of exiting, CLI tools prompting for input, slow startup on CI, or forgetting that long-lived processes never 'exit' and should be waited on differently.
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
- waitForOutput 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/82af34d1b4eb48b7.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/process/ProcessHandle.java:342
public int waitSync() {
try {
int code = exitFuture.get();
// Wait for stream readers to complete so all output is captured
waitForStreamReaders();
return code;
} catch (Exception e) {
throw new RuntimeException("error waiting for process", e);
}
}
public int waitSync(long timeoutMillis) {
try {
int code = exitFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);
// Wait for stream readers to complete so all output is captured
waitForStreamReaders();
return code;
} catch (TimeoutException e) {
throw new RuntimeException("process timed out after " + timeoutMillis + "ms");
} catch (Exception e) {
throw new RuntimeException("error waiting for process", e);
}
}
/**
* Wait for all stream reader threads to complete.
* This ensures all output is captured before getStdOut()/getStdErr() is called.
* <p>
* After process exit, stream readers complete almost instantly since the OS
* closes the pipes. We use a short timeout as a safety net.
*/
private void waitForStreamReaders() {
try {
// Streams close immediately after process exit, so this should be near-instant.
// Use 500ms timeout as safety net (never hit in practice).
if (stdoutReaderDone != null && !stdoutReaderDone.isDone()) {
stdoutReaderDone.get(500, TimeUnit.MILLISECONDS);View on GitHub (pinned to a22eb90246)