apache/seatunnel · error · IOException

python.executable does not resolve to an executable file: {}

Error message

python.executable does not resolve to an executable file: {}

What it means

Thrown after resolving python.executable when the resolved location is not a regular executable file (missing file, directory, broken symlink, or no execute permission). The policy validates before spawning so the failure is reported clearly instead of failing at process start.

Source

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

    private static Path resolveConfiguredExecutable(String configuredExecutable)
            throws IOException {
        Path configuredPath = Paths.get(configuredExecutable);
        Path resolvedPath;
        if (configuredPath.isAbsolute()) {
            resolvedPath = normalize(configuredPath);
        } else if (configuredPath.getParent() == null) {
            resolvedPath = resolveCommandFromPath(configuredExecutable);
            if (resolvedPath == null) {
                throw new IOException(
                        "Unable to resolve python.executable from PATH: " + configuredExecutable);
            }
        } else {
            throw new IllegalStateException(
                    "python.executable must be an absolute path or a bare command name: "
                            + configuredExecutable);
        }
        if (!Files.isRegularFile(resolvedPath) || !Files.isExecutable(resolvedPath)) {
            throw new IOException(
                    "python.executable does not resolve to an executable file: " + resolvedPath);
        }
        return resolvedPath;
    }

    private static Path resolveCommandFromPath(String command) {
        String pathValue = System.getenv("PATH");
        if (pathValue == null || pathValue.trim().isEmpty()) {
            return null;
        }
        for (String directory : pathValue.split(Pattern.quote(File.pathSeparator))) {
            if (directory == null || directory.trim().isEmpty()) {
                continue;
            }
            for (String commandName : expandCommandNames(command)) {
                Path candidate = Paths.get(directory, commandName);
                if (Files.isRegularFile(candidate) && Files.isExecutable(candidate)) {
                    return normalize(candidate);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Verify the file exists and is executable: ls -l $(configured-path) and test -x
  2. Reinstall or relink the interpreter (recreate the venv)
  3. Fix permissions: chmod +x /path/to/python, or choose an interpreter the runtime user can execute
  4. Ensure the path is also allowlisted in python.allowed.executables

Example fix

// before
pythonExecutable = "/opt/old-venv/bin/python"  # deleted
// after
pythonExecutable = "/usr/bin/python3"
Defensive patterns

Strategy: validation

Validate before calling

Path p = Paths.get(config.getPythonExecutable());
if (!java.nio.file.Files.isRegularFile(p) || !java.nio.file.Files.isExecutable(p))
    throw new IllegalArgumentException("Not an executable file: " + p);

Prevention

When it happens

Trigger: Configured path points to a nonexistent file, a directory (e.g. /usr/bin), or a file without +x permission; also reachable after PATH resolution finds a non-executable match.

Common situations: Interpreter removed/upgraded after config was written; dangling symlink after venv relocation; running as a user lacking execute permission on the binary.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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