kestra-io / kestra-io/plugin-scripts
Python tasks fail with NullPointerException on Windows: HOME is not defined
- 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