fix(trainer): `get_script_for_python_packages` raises `IndexError` when `pip_index_urls` is empty
- Dominant language
- Python
- Stars
- 148
- Forks
- 262
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 1
Description
### What happened?
In [`kubeflow/trainer/backends/kubernetes/utils.py`](file:///c:/Users/Vishal/Code_File/Repo%20Folder/sdk/kubeflow/trainer/backends/kubernetes/utils.py#L289-L294), the utility function `get_script_for_python_packages` constructs the pip install options by directly indexing `pip_index_urls[0]`:
```python
# first url will be the index-url.
options = [f"--index-url {shlex.quote(pip_index_urls[0])}"]
options.extend(
f"--extra-index-url {shlex.quote(extra_index_url)}"
for extra_index_url in pip_index_urls[1:]
)
options_str = " ".join(options)
```
When a user defines a `CustomTrainer` with `packages_to_install` specified but sets `pip_index_urls=[]` (an empty list), `get_script_for_python_packages` is invoked during `get_command_using_train_func` ([`utils.py#L388-L393`](file:///c:/Users/Vishal/Code_File/Repo%20Folder/sdk/kubeflow/trainer/backends/kubernetes/utils.py#L388-L393)).
Because `pip_index_urls` is empty, evaluating `pip_index_urls[0]` causes an uncaught runtime exception:
```text
IndexError: list index out of range
```
#### Reproduction Code Example
```python
from kubeflow.trainer import TrainerClient
from kubeflow.trainer.types import CustomTrainer
def train_fn():
import numpy as np
print("Training...", np.__version__)
trainer = CustomTrainer(
func=train_fn,
packages_to_install=["numpy"],
pip_index_urls=[], # Empty list to rely on default pip configuration
)
# Throws IndexError: list index out of range when building trainer CR command
client = TrainerClient()
client.train(trainer=trainer)
```
---
### What did you expect to happen?
`get_script_for_python_packages` should safely check if `pip_index_urls` contains elements before accessing `pip_index_urls[0]`. If `pip_index_urls` is an empty list `[]`, it should not append any `--index-url` or `--extra-index-url` flags to options, allowing pip to proceed with standard default index behavior without throwing an unhandled `IndexError`.
Proposed fix in [`kubeflow/trainer/backends/kubernetes/utils.py`](file:///c:/Users/Vishal/Code_File/Repo%20Folder/sdk/kubeflow/trainer/backends/kubernetes/utils.py#L289-L295):
```python
options = []
if pip_index_urls:
options.append(f"--index-url {shlex.quote(pip_index_urls[0])}")
options.extend(
f"--extra-index-url {shlex.quote(extra_index_url)}"
for extra_index_url in pip_index_urls[1:]
)
options_str = " ".join(options)
```
---
### Environment
Kubernetes version:
```bash
$ kubectl version
Client Version: v1.30.0
```
Kubeflow Trainer version:
```bash
$ kubectl get pods -n kubeflow -l app.kubernetes.io/name=trainer -o jsonpath="{.items[*].spec.containers[*].image}"
ghcr.io/kubeflow/trainer-controller:v1.0.0
```
Kubeflow Python SDK version:
```bash
$ pip show kubeflow
Name: kubeflow
Version: 0.4.1
```
---
### Impacted by this bug?
Give it a 👍 We prioritize the issues with most 👍
Contributor guide
Assessment
This issue has not been assessed yet.