mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-30 01:52:18 +00:00
fix(vector-stores): raise BadRequestError (400) for invalid Vertex Search extra_body
Rejecting unsupported or target-selecting extra_body fields previously raised a bare ValueError, which the vector store error path mapped to a generic APIConnectionError (HTTP 500). Raise litellm.BadRequestError so invalid per-request input surfaces as HTTP 400 with a clear message.
This commit is contained in:
parent
6037ac7668
commit
d4f515e3f2
2 changed files with 35 additions and 17 deletions
|
|
@ -3,6 +3,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
|
|||
import httpx
|
||||
|
||||
from litellm import get_model_info
|
||||
from litellm.exceptions import BadRequestError
|
||||
from litellm.litellm_core_utils.url_utils import encode_url_path_segment
|
||||
from litellm.llms.base_llm.vector_store.transformation import BaseVectorStoreConfig
|
||||
from litellm.llms.vertex_ai.vertex_llm_base import VertexBase
|
||||
|
|
@ -85,11 +86,12 @@ class VertexSearchAPIVectorStoreConfig(BaseVectorStoreConfig, VertexBase):
|
|||
Validate ``extra_body`` against the supported-field allowlist for the
|
||||
active serving config (engine/app vs data store).
|
||||
|
||||
Raises ``ValueError`` if the caller includes a target-selecting field
|
||||
(e.g. ``servingConfig``) or any field not supported for the active mode,
|
||||
so the request fails loudly instead of silently searching the wrong
|
||||
target. Engine-only fields (``dataStoreSpecs``, ``numResultsPerDataStore``)
|
||||
are rejected in data-store mode where they are meaningless.
|
||||
Raises ``BadRequestError`` (HTTP 400) if the caller includes a
|
||||
target-selecting field (e.g. ``servingConfig``) or any field not
|
||||
supported for the active mode, so the request fails loudly instead of
|
||||
silently searching the wrong target. Engine-only fields
|
||||
(``dataStoreSpecs``, ``numResultsPerDataStore``) are rejected in
|
||||
data-store mode where they are meaningless.
|
||||
"""
|
||||
supported = cls.get_supported_extra_body_fields(is_engine=is_engine)
|
||||
filtered = {
|
||||
|
|
@ -98,18 +100,26 @@ class VertexSearchAPIVectorStoreConfig(BaseVectorStoreConfig, VertexBase):
|
|||
|
||||
target_selecting = set(filtered) & VERTEX_SEARCH_TARGET_SELECTING_FIELDS
|
||||
if target_selecting:
|
||||
raise ValueError(
|
||||
"Vertex AI Search extra_body may not set target-selecting fields "
|
||||
f"{sorted(target_selecting)}: the data store is scoped by "
|
||||
"vector_store_id / vertex_engine_id and cannot be overridden per request."
|
||||
raise BadRequestError(
|
||||
message=(
|
||||
"Vertex AI Search extra_body may not set target-selecting fields "
|
||||
f"{sorted(target_selecting)}: the data store is scoped by "
|
||||
"vector_store_id / vertex_engine_id and cannot be overridden per request."
|
||||
),
|
||||
model="vertex_ai/search_api",
|
||||
llm_provider="vertex_ai",
|
||||
)
|
||||
|
||||
unsupported = set(filtered) - supported
|
||||
if unsupported:
|
||||
mode = "engine/app" if is_engine else "data store"
|
||||
raise ValueError(
|
||||
f"Unsupported Vertex AI Search extra_body fields {sorted(unsupported)} "
|
||||
f"for {mode} mode. Supported fields: {sorted(supported)}."
|
||||
raise BadRequestError(
|
||||
message=(
|
||||
f"Unsupported Vertex AI Search extra_body fields {sorted(unsupported)} "
|
||||
f"for {mode} mode. Supported fields: {sorted(supported)}."
|
||||
),
|
||||
model="vertex_ai/search_api",
|
||||
llm_provider="vertex_ai",
|
||||
)
|
||||
|
||||
return filtered
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from types import SimpleNamespace
|
|||
|
||||
import pytest
|
||||
|
||||
from litellm.exceptions import BadRequestError
|
||||
from litellm.llms.vertex_ai.vector_stores.search_api.transformation import (
|
||||
VertexSearchAPIVectorStoreConfig,
|
||||
)
|
||||
|
|
@ -209,32 +210,39 @@ def test_engine_search_request_forwards_num_results_per_data_store():
|
|||
def test_datastore_search_request_rejects_datastorespecs():
|
||||
specs = [{"dataStore": "projects/p/.../dataStores/ds-beta"}]
|
||||
|
||||
with pytest.raises(ValueError, match="data store mode"):
|
||||
with pytest.raises(BadRequestError, match="data store mode"):
|
||||
_datastore_search_request(extra_body={"dataStoreSpecs": specs})
|
||||
|
||||
|
||||
def test_datastore_search_request_rejects_num_results_per_data_store():
|
||||
with pytest.raises(ValueError, match="data store mode"):
|
||||
with pytest.raises(BadRequestError, match="data store mode"):
|
||||
_datastore_search_request(extra_body={"numResultsPerDataStore": 3})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("field", ["branch", "servingConfig", "entity"])
|
||||
def test_search_request_rejects_target_selecting_fields(field):
|
||||
with pytest.raises(ValueError, match="target-selecting"):
|
||||
with pytest.raises(BadRequestError, match="target-selecting"):
|
||||
_search_request(extra_body={field: "x"})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("field", ["branch", "servingConfig", "entity"])
|
||||
def test_datastore_search_request_rejects_target_selecting_fields(field):
|
||||
with pytest.raises(ValueError, match="target-selecting"):
|
||||
with pytest.raises(BadRequestError, match="target-selecting"):
|
||||
_datastore_search_request(extra_body={field: "x"})
|
||||
|
||||
|
||||
def test_search_request_rejects_unsupported_extra_body_field():
|
||||
with pytest.raises(ValueError, match="Unsupported Vertex AI Search extra_body"):
|
||||
with pytest.raises(BadRequestError, match="Unsupported Vertex AI Search extra_body"):
|
||||
_search_request(extra_body={"notARealField": True})
|
||||
|
||||
|
||||
def test_rejected_extra_body_raises_http_400():
|
||||
with pytest.raises(BadRequestError) as exc_info:
|
||||
_search_request(extra_body={"notARealField": True})
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
|
||||
|
||||
def test_search_request_forwards_supported_extra_body_fields():
|
||||
_, body = _search_request(
|
||||
extra_body={
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue