apache/seatunnel · critical · IllegalStateException

Failed to consume python source stderr

Error message

Failed to consume python source stderr

What it means

PythonSourceReader runs a background thread consuming the Python subprocess's stderr to prevent pipe deadlock. If that stderr pump thread throws, the failure is stored in stderrPumpFailure and rethrown as an IllegalStateException by checkPumpFailures, which is invoked from pollNext and verifyProcessExit. It signals that diagnostics from the Python process can no longer be captured and the reader is in a failed state.

Solutions

  1. Inspect getCause() for the underlying stderr pump failure
  2. Run the Python script manually and watch stderr for crash messages (tracebacks, OOM, import errors)
  3. Ensure the child process is not being killed by the OS (check dmesg/oom-killer logs, raise memory limits)
  4. Confirm Python interpreter version and dependencies are correct on every worker node

Example fix

// before
throw new IllegalStateException(
        "Failed to consume python source stderr", stderrPumpFailure);
// after
LOG.error("python stderr pump failed; inspect python script stderr for a traceback",
        stderrPumpFailure.getCause());
throw new IllegalStateException(
        "Failed to consume python source stderr", stderrPumpFailure);
Defensive patterns

Strategy: try-catch

Validate before calling

// run the script and capture stderr before deploying
Process p = new ProcessBuilder(pythonScriptArgs).redirectErrorStream(false).start();
String stderr = new String(p.getErrorStream().readAllBytes());
if (!stderr.isEmpty()) LOG.warn("python stderr during dry-run: {}", stderr);

Try / catch

try {
    reader.pollNext();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Failed to consume python source stderr")) {
        LOG.error("python stderr pump failed", e.getCause());
    } else throw e;
}

Prevention

When it happens

Trigger: The stderr pump thread throws while reading the child's stderr stream; the failure is rethrown on the next pollNext or verifyProcessExit call through checkPumpFailures.

Common situations: Python process dies abruptly (OOM-kill, SIGKILL) closing the stderr pipe; I/O error reading the pipe; overly verbose stderr causing backpressure or reader errors; environment issues causing the Python interpreter to emit unexpected output.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/08f823cf44610905. Report an issue: GitHub.

Appendix: source

Thrown at seatunnel-connectors-v2/connector-python/src/main/java/org/apache/seatunnel/connectors/seatunnel/python/source/PythonSourceReader.java:629

            return;
        }
        try {
            thread.join(PROCESS_EXIT_CHECK_TIMEOUT_MILLIS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("Interrupted while draining python source process output", e);
        }
    }

    private void checkPumpFailures() {
        if (stdoutPumpFailure != null) {
            throw new IllegalStateException(
                    "Failed to consume python source stdout", stdoutPumpFailure);
        }
        if (stderrPumpFailure == null) {
            return;
        }
        throw new IllegalStateException(
                "Failed to consume python source stderr", stderrPumpFailure);
    }

    /** Registers one poll so close cannot return while rows or completion are still emitted. */
    private boolean beginPoll() {
        synchronized (lifecycleLock) {
            if (noMoreSplits || closeRequested) {
                return false;
            }
            activePolls++;
            return true;
        }
    }

    /** Releases the close barrier after every row and terminal signal has completed. */
    private void endPoll() {
        synchronized (lifecycleLock) {
            activePolls--;

View on GitHub (pinned to cf67b549a7)