karatelabs/karate · warning

timeout waiting for stream readers - this should not happen

Error message

timeout waiting for stream readers - this should not happen

What it means

When a process handle's `waitSync` finishes waiting on the process, it gives each stream-reader future a short 500ms window to complete. If a reader still hasn't finished after that, this warning is logged. It indicates the stdout/stderr pump threads are unexpectedly stuck and output may not have been fully drained.

Solutions

  1. Ensure child processes redirect their own output (e.g. redirect grandchildren to files or /dev/null)
  2. Check for orphaned grandchildren keeping the pipe open and kill them
  3. Drain streams promptly so pump threads never block on back-pressure
  4. Treat as diagnostic: investigate why output did not finish shortly after process exit
Defensive patterns

Strategy: try-catch

Try / catch

try { handle.waitSync(); }
catch (Exception e) { log.warn("process teardown issue", e); } // the warn inside is the real signal: check for orphaned grandchildren

Prevention

When it happens

Trigger: A child process's stdout or stderr pipe remains open after process exit — typically because a grandchild inherited the pipe and is still running; extremely large buffered output not yet consumed within 500ms.

Common situations: Spawning scripts that launch background children which inherit the streams; daemon threads of the child still writing after main exit; pipe buffer back-pressure due to a reader that stopped consuming.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/process/ProcessHandle.java:366

    /**
     * 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);
            }
            if (stderrReaderDone != null && !stderrReaderDone.isDone()) {
                stderrReaderDone.get(500, TimeUnit.MILLISECONDS);
            }
        } catch (TimeoutException e) {
            logger.warn("timeout waiting for stream readers - this should not happen");
        } catch (Exception e) {
            logger.debug("error waiting for stream readers: {}", e.getMessage());
        }
    }

    /**
     * Wait until predicate returns true for an output line.
     *
     * @param predicate Test function that receives the line
     * @return The line that matched
     */
    public String waitForOutput(Predicate<String> predicate) {
        return waitForOutput(predicate, 0);
    }

    /**
     * Wait until predicate returns true for an output line, with timeout.
     *

View on GitHub (pinned to a22eb90246)