apache/seatunnel · warning

Python source thread did not finish within ms while…

Error message

Python source {} thread did not finish within {}ms while closing; it may keep running along with any descendant process it holds open

What it means

During close(), the Python source reader joins its worker thread with a bounded timeout. If the thread does not finish in time and no earlier close failure was recorded, it logs this warning instead of failing the close — because the leaked thread (and any child process it keeps alive) would otherwise be invisible.

Solutions

  1. Make the Python script respond to EOF/cancellation promptly (close streams, handle SIGTERM)
  2. Increase the close timeout so legitimate slow shutdowns complete
  3. Check the running script for child processes it spawns that keep handles open
  4. If the warning recurs, terminate the leaked process at the OS level (kill the resolved executable pid)
Defensive patterns

Strategy: fallback

Validate before calling

// ensure the script exits promptly on EOF
final String scriptCheck = "import sys; sys.stdin.readline(); sys.exit(0)"; // verify behaves so under timeout

Try / catch

try { reader.close(); } catch (IOException e) { /* closeException from join timeout */ log.warn("python reader close incomplete: {}", e.getMessage()); }

Prevention

When it happens

Trigger: joinThread is called from close(); streamCloser/reader thread does not terminate within timeoutMillis; failOnTimeout=false or an earlier join already produced closeException, so it is logged rather than thrown.

Common situations: Python script blocked on reading stdin or a long computation that ignores cancellation; descendant processes inherited from the Python process keeping the pipe open; very short close timeouts.

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.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/005d03986ccbde71. 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:712

        if (closeRequested) {
            thread.interrupt();
        }
        try {
            thread.join(timeoutMillis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            if (closeException == null) {
                return new IOException("Interrupted while closing python source " + threadName, e);
            }
        }
        if (thread.isAlive()) {
            if (failOnTimeout && closeException == null) {
                return new IOException("Timed out while closing python source " + threadName);
            }
            // Not surfaced as a close failure (failOnTimeout=false, or an earlier join already
            // produced closeException), but the thread outliving its bounded join is otherwise
            // invisible: log it so a leaked thread or inherited descendant is observable.
            LOG.warn(
                    "Python source {} thread did not finish within {}ms while closing; it may keep"
                            + " running along with any descendant process it holds open",
                    threadName,
                    timeoutMillis);
        }
        return closeException;
    }

    private synchronized void appendStderrLine(String line) {
        if (recentStderrLines.size() == STDERR_HISTORY_LIMIT) {
            recentStderrLines.removeFirst();
        }
        recentStderrLines.addLast(line);
    }

    private synchronized String formatRecentStderr() {
        if (recentStderrLines.isEmpty()) {
            return "";

View on GitHub (pinned to cf67b549a7)