kestra-io / kestra-io/plugin-scripts

Python tasks fail with NullPointerException on Windows: HOME is not defined

Open
#441 0 comments 0 reactions 0 assignees View on GitHub
area/backend area/plugin
Dominant language
Java
Stars
19
Forks
33
Avg merge
2d 12h
Merged PRs (30d)
9

Description

## What happens

On Windows, every `io.kestra.plugin.scripts.python.Script` task fails before `beforeCommands` or the script are reached:

```
java.lang.NullPointerException: Cannot invoke "java.lang.CharSequence.toString()" because "" is null
at java.base/java.lang.String.replace(Unknown Source)
at io.kestra.plugin.scripts.python.internals.PythonDependenciesResolver.getUvCmd(PythonDependenciesResolver.java:339)
at io.kestra.plugin.scripts.python.internals.PythonDependenciesResolver.findPython(PythonDependenciesResolver.java:566)
at io.kestra.plugin.scripts.python.internals.PythonDependenciesResolver.findLocalPythonVersion(PythonDependenciesResolver.java:152)
at io.kestra.plugin.scripts.python.internals.PythonEnvironmentManager.setup(PythonEnvironmentManager.java:79)
at io.kestra.plugin.scripts.python.Script.run(Script.java:358)
```

## Cause

`PythonDependenciesResolver.java:36`:

```java
private static final String HOME_ENV = System.getenv("HOME");
```

**Windows does not define `HOME`** (it has `USERPROFILE`), so `HOME_ENV` is `null`. Two consequences:

1. **Line 339** — `Optional.ofNullable(System.getenv("UV_PATH")).orElse("$HOME/.local/bin/uv".replace("$HOME", HOME_ENV))` → `String.replace(target, null)`. Because `orElse` evaluates its argument eagerly, this throws **even when `UV_PATH` is set**, so there is no way to configure around it.
2. **Lines 384, 540, 577** — `env.put("HOME", HOME_ENV)` on a `ProcessBuilder` environment. Windows' `ProcessEnvironment` rejects a null value, which surfaces as a second NPE: `Cannot invoke "String.indexOf(int)" because "" is null`.

Code is identical in `v1.9.8` and `v1.9.10`.

## Reproduction

Kestra 1.3.37 standalone on Windows Server 2022, `plugin-script-python` 1.9.8, Process task runner:

```yaml
id: python-probe
namespace: test
tasks:
- id: hello
type: io.kestra.plugin.scripts.python.Script
taskRunner:
type: io.kestra.plugin.core.runner.Process
script: |
print("hello")
```

Fails the same way with no Python installed, with system Python 3.12 + uv 0.12.15 on `PATH`, with a uv-managed interpreter and `UV_PYTHON_INSTALL_DIR` set, and with `pythonVersion` named explicitly.

## Confirmation

Setting `HOME` in the server's environment removes the NPE, and the resolver then works correctly on Windows:

```
uv --version → uv 0.12.15 (x86_64-pc-windows-msvc)
uv python find --system --no-managed-python → C:\Python312\python.exe
C:\Python312\python.exe --version → Python 3.12.10
```

(The task then needs `interpreter: ["cmd", "/c"]`, since `AbstractExecScript` defaults to `/bin/sh -c` — a separate matter — after which it runs: `cmd /c python3 …py`, exit 0.)

## Suggested fix

Resolve the home directory portably — `HOME`, then `USERPROFILE`, then `System.getProperty("user.home")`, which the JVM always sets — and make line 339 use `orElseGet` so the default path is not computed when `UV_PATH` is set. Happy to open a PR.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in PythonDependenciesResolver.java, especially the HOME_ENV declaration and lines 339, 384, 540, and 577, then trace the call from PythonEnvironmentManager.setup and Script.run. Reproduce the Windows failure with the provided Python task and verify that resolution reaches the script without HOME-related exceptions, including when UV_PATH is set.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.