fix(s3_vectors): reject a store id with an empty bucket or index part

A "bucket:" or ":index" id split into an empty name, so ingestion silently
generated a fresh index and search sent the empty name to AWS. Both sides now
raise the existing format error through the shared helper.
This commit is contained in:
mateo-berri 2026-09-19 03:52:48 -07:00
parent e2d118aaf8
commit e4d01d1d78
3 changed files with 34 additions and 5 deletions

View file

@ -33,12 +33,12 @@ S3_VECTORS_STORE_ID_ERROR: Final = (
def split_s3_vectors_store_id(vector_store_id: str, fallback_bucket_name: object) -> tuple[str, str]:
if ":" in vector_store_id:
bucket_name, index_name = vector_store_id.split(":", 1)
return bucket_name, index_name
if not isinstance(fallback_bucket_name, str) or not fallback_bucket_name:
id_bucket_name, separator, id_index_name = vector_store_id.partition(":")
bucket_name: Final = id_bucket_name if separator else fallback_bucket_name
index_name: Final = id_index_name if separator else vector_store_id
if not isinstance(bucket_name, str) or not bucket_name or not index_name:
raise ValueError(S3_VECTORS_STORE_ID_ERROR)
return fallback_bucket_name, vector_store_id
return bucket_name, index_name
class S3VectorsVectorStoreConfig(BaseQueryEmbeddingVectorStoreConfig, BaseAWSLLM):

View file

@ -236,6 +236,22 @@ class TestS3VectorsVectorStoreConfig:
assert executor.calls == []
@pytest.mark.parametrize("vector_store_id", ["test-bucket:", ":test-index"])
def test_transform_search_request_rejects_an_empty_bucket_or_index_in_the_id(self, vector_store_id):
config = S3VectorsVectorStoreConfig()
executor = _RecordingExecutor()
with pytest.raises(ValueError, match="vector_store_id must be in format 'bucket_name:index_name'"):
config.transform_search_vector_store_request(
**_search_kwargs(
vector_store_id=vector_store_id,
litellm_params={"vector_bucket_name": "test-bucket"},
embedding_executor=executor,
)
)
assert executor.calls == []
def test_transform_search_request_bucket_from_litellm_params(self):
config = S3VectorsVectorStoreConfig()

View file

@ -50,3 +50,16 @@ def test_bucket_alone_leaves_the_index_to_be_generated():
def test_no_bucket_anywhere_is_rejected(vector_store):
with pytest.raises(ValueError, match=STORE_ID_FORMAT_ERROR):
_ingestion(**vector_store)
@pytest.mark.parametrize(
"vector_store",
[
{"vector_store_id": "my-embeddings:"},
{"vector_store_id": ":my-index"},
{"vector_store_id": "my-embeddings:", "vector_bucket_name": "my-embeddings"},
],
)
def test_an_empty_bucket_or_index_in_the_store_id_is_rejected_instead_of_generating_an_index(vector_store):
with pytest.raises(ValueError, match=STORE_ID_FORMAT_ERROR):
_ingestion(**vector_store)