{"record":{"id":"bfe02ca70be92ea8","repo":"karatelabs/karate","slug":"waitforoutput-timed-out-after-ms","errorCode":null,"errorMessage":"waitForOutput timed out after ms","messagePattern":"waitForOutput timed out after ms","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/process/ProcessHandle.java","lineNumber":402,"sourceCode":"     *\n     * @param predicate     Test function that receives the line\n     * @param timeoutMillis Timeout in milliseconds (0 = no timeout)\n     * @return The line that matched\n     */\n    public String waitForOutput(Predicate<String> predicate, long timeoutMillis) {\n        CompletableFuture<String> future = new CompletableFuture<>();\n        waitPredicates.add(predicate);\n        waitFutures.put(predicate, future);\n        try {\n            if (timeoutMillis > 0) {\n                return future.get(timeoutMillis, TimeUnit.MILLISECONDS);\n            } else {\n                return future.get();\n            }\n        } catch (TimeoutException e) {\n            waitPredicates.remove(predicate);\n            waitFutures.remove(predicate);\n            throw new RuntimeException(\"waitForOutput timed out after \" + timeoutMillis + \"ms\");\n        } catch (Exception e) {\n            waitPredicates.remove(predicate);\n            waitFutures.remove(predicate);\n            throw new RuntimeException(\"error in waitForOutput\", e);\n        }\n    }\n\n    public String getStdOut() {\n        synchronized (stdoutBuffer) {\n            return stdoutBuffer.toString();\n        }\n    }\n\n    public String getStdErr() {\n        synchronized (stderrBuffer) {\n            return stderrBuffer.toString();\n        }\n    }","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/process/ProcessHandle.java#L384-L420","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"// before\nhandle.waitForOutput(\"Server is ready\", 5_000); // banner actually is \"Listening on...\"\n// after\nhandle.waitForOutput(\"Listening on\", 30_000); // or readyLine():\nhandle.readyLine(30_000);","handlingStrategy":"try-catch","validationCode":"if (timeoutMillis < expectedStartupUpperBoundMs) {\n    throw new IllegalArgumentException(\"waitForOutput timeout \" + timeoutMillis + \"ms below expected startup bound\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    handle.waitForOutput(\"Started\", 30_000);\n} catch (RuntimeException e) {\n    if (e.getMessage().startsWith(\"waitForOutput timed out\")) {\n        log.error(\"process output so far: stdout={} stderr={}\", handle.getStdOut(), handle.getStdErr());\n        handle.stop(5_000);\n    } else {\n        throw e;\n    }\n}","preventionTips":["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"],"tags":["process","timeout","output","wait"],"backgroundTag":"request-timeout","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}