googleapis / googleapis/python-aiplatform
Bug: create_tree_ah_index() fails when leaf parameters are not specified (regression from PR #5954)
- Dominant language
- Python
- Stars
- 905
- Forks
- 465
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 44
Description
**PLEASE READ**: I have searched existing issues and StackOverflow before creating this report.
## Environment details
- OS type and version: macOS
- Python version: 3.12
- pip version: 24.0
- `google-cloud-aiplatform` version: >= 1.71.0 (after PR #5954)
## Steps to reproduce
1. Call `MatchingEngineIndex.create_tree_ah_index()` without specifying `leaf_node_embedding_count` or `leaf_nodes_to_search_percent`
2. The API returns an error: `algorithmConfig is required but missing from the metadata`
## Code example
```python
from google.cloud import aiplatform
aiplatform.init(project="my-project", location="us-central1")
# This fails
index = aiplatform.MatchingEngineIndex.create_tree_ah_index(
display_name="my-index",
dimensions=768,
approximate_neighbors_count=150,
distance_measure_type="DOT_PRODUCT_DISTANCE",
# Note: leaf_node_embedding_count and leaf_nodes_to_search_percent are NOT specified
)
```
## Stack trace
```
algorithmConfig is required but missing from the metadata
```
---
## Additional Context
### Description
`MatchingEngineIndex.create_tree_ah_index()` fails when neither `leaf_node_embedding_count` nor `leaf_nodes_to_search_percent` is specified, because `algorithmConfig` is set to `None` instead of `{"treeAhConfig": {}}`.
According to the [official documentation](https://cloud.google.com/vertex-ai/docs/vector-search/configuring-indexes), `algorithmConfig` is a **required** field that must contain either `TreeAhConfig` or `BruteForceConfig`. Setting it to `null` causes the API to reject the request.
### Expected Behavior
The REST API expects:
```json
{
"metadata": {
"config": {
"dimensions": 768,
"approximateNeighborsCount": 150,
"algorithmConfig": {
"treeAhConfig": {}
}
}
}
}
```
### Actual Behavior
The SDK sends:
```json
{
"metadata": {
"config": {
"dimensions": 768,
"approximateNeighborsCount": 150,
"algorithmConfig": null
}
}
}
```
### Root Cause
This regression was introduced in PR #5954 (merged 2025-10-21).
The intent of PR #5954 was to make the `treeAhConfig` parameters (`leaf_node_embedding_count`, `leaf_nodes_to_search_percent`) optional. However, the implementation incorrectly sets `algorithmConfig` itself to `None` instead of sending an empty `treeAhConfig: {}`.
**Before PR #5954** (`matching_engine_index.py`):
```python
algorithm_config = matching_engine_index_config.TreeAhConfig(
leaf_node_embedding_count=leaf_node_embedding_count,
leaf_nodes_to_search_percent=leaf_nodes_to_search_percent,
)
```
**After PR #5954**:
```python
algorithm_config = None
if (
leaf_node_embedding_count is not None
or leaf_nodes_to_search_percent is not None
):
algorithm_config = matching_engine_index_config.TreeAhConfig(
leaf_node_embedding_count=leaf_node_embedding_count,
leaf_nodes_to_search_percent=leaf_nodes_to_search_percent,
)
```
The `TreeAhConfig.as_dict()` method already handles `None` values correctly, so creating a `TreeAhConfig()` with default `None` values would generate valid JSON that the API accepts.
### Proposed Fix
Revert the conditional logic for `create_tree_ah_index()` to always create a `TreeAhConfig`:
```python
algorithm_config = matching_engine_index_config.TreeAhConfig(
leaf_node_embedding_count=leaf_node_embedding_count,
leaf_nodes_to_search_percent=leaf_nodes_to_search_percent,
)
```
### Workaround
Explicitly specify at least one of the optional parameters:
```python
index = aiplatform.MatchingEngineIndex.create_tree_ah_index(
display_name="my-index",
dimensions=768,
approximate_neighbors_count=150,
distance_measure_type="DOT_PRODUCT_DISTANCE",
leaf_node_embedding_count=1000, # Explicitly specify default value
)
```
### Related
- PR #5954: "chore: Make MatchingEngineIndexConfig's algorithmConfig optional" (introduced this regression)
- Issue #2967: "MatchingEngineIndex create_tree_ah_index fails" (similar but different root cause, fixed in 1.36.4)
### Impact
Users following official Google tutorials and notebooks that don't specify `leaf_node_embedding_count` or `leaf_nodes_to_search_percent` will encounter this error.
### Next Steps
I am implementing a PR to fix this issue. I'll push it soon. The fix is straightforward - just revert the conditional logic in `create_tree_ah_index()` to always create a `TreeAhConfig`.
Contributor guide
Research direction
Start in matching_engine_index.py at MatchingEngineIndex.create_tree_ah_index() and inspect the conditional construction of algorithm_config. Verify how TreeAhConfig.as_dict() serializes default None values, then run the relevant existing MatchingEngineIndex tests. Done means calls without either leaf parameter produce an empty treeAhConfig instead of null and are accepted by the API.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100