Repository navigation
Python: Cosmos NoSQL collection_exists reports a throttled request as a missing container - #14515
Eric Del Orefice (ericdelorefice) wants to merge 2 commits into
Conversation
… a missing container collection_exists caught CosmosHttpResponseError and returned False. That is the parent of every Cosmos HTTP error, so a 401, 403, 429 or 5xx all reported that the container does not exist. _does_database_exist in the same connector already answers the equivalent question correctly: CosmosResourceNotFoundError returns False and anything else raises VectorStoreOperationException. collection_exists now mirrors it. Three tests, none existed for collection_exists on this collection. A missing container returns False, a 429 raises, a successful read returns True. Against main only the 429 test fails.
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The focused implementation matches the existing database behavior and covers the relevant outcomes.
Review effort: Balanced
Findings: None
What changed in this PR
Narrows Cosmos NoSQL existence handling so only missing containers return False.
Changes:
- Wraps throttling and other failures in
VectorStoreOperationException. - Adds tests for missing, throttled, and successful reads.
| File | Description |
|---|---|
python/semantic_kernel/connectors/azure_cosmos_db.py |
Corrects container existence error handling. |
python/tests/unit/connectors/memory/azure_cosmos_db/test_azure_cosmos_db_no_sql_collection.py |
Tests the corrected behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
PRABHU KIRAN VANDRANKI (VANDRANKI)
left a comment
There was a problem hiding this comment.
This is a community review and does not clear the merge gate. I ran this on Windows against upstream main at 64005c7, with azure-cosmos 4.17.1.
The change is right. CosmosResourceNotFoundError is a subclass of CosmosHttpResponseError (I checked), so the old except CosmosHttpResponseError: return False did turn a 429, 401, 403 or 5xx into "container does not exist", and the new code only does that for a 404. It also matches the abstract docstring in data/vector.py, which asks implementations to raise relevant exceptions with good descriptions.
What I ran:
- The test file on the branch: all pass, including the three new
collection_existstests. - The same test file against main's source: only
test_azure_cosmos_db_no_sql_collection_exists_raises_on_a_throttled_requestfails. The other two new tests pass on main as well, since they describe behavior main already had, so they are only guards.
Two things I hit that this PR does not change, so they are context and not requests. I used a mocked CosmosClient here, not a live account:
collection_existscalls_get_container_proxybefore thetry, and that goes through_get_database_proxy. With the database missing andcreate_database=False,collection_exists()raisesVectorStoreOperationException("Failed to get container proxy for 'c'.")and does not returnFalse. So "false when the container is missing" only holds when the database exists.- With the database missing and
create_database=True, the same call creates the database (create_databasewas awaited once in my probe). A pure existence check with a write side effect is surprising, though it predates this PR.
The PR text already notes that VectorStore.collection_exists turns VectorStoreOperationException into False. I read that wrapper at data/vector.py lines 1576 to 1587 and agree: at the store level, a throttled container still reads as absent after this change. The collection-level fix still matters, since CosmosNoSqlCollection.collection_exists is the public method on the collection.
Small test note: the three new tests mock _get_container_proxy, so none of them exercises the path in point 1.
The connector only imports on chromadb 1.x (it needs chromadb.api.collection_configuration), so the ValueError fallback for chromadb < 1.0 could never run; it is removed, with the two tests it gated. collection_exists now wraps any other error in VectorStoreOperationException, matching ensure_collection_deleted here and the Cosmos NoSQL change in microsoft#14515.
|
Thank you for running this against main and checking the exception hierarchy. That was the part I most wanted someone else to look at. You're right that both of your notes predate this PR, so I've kept it to the one change. The first is real: with the database missing and Agreed on the store level too. 🤖 Addressed by Claude Code |
Motivation and Context
CosmosNoSqlCollection.collection_existscatchesCosmosHttpResponseErrorand returnsFalse. That is the parent class of every Cosmos HTTP error, so a 401, a 403, a 429 or a 5xx all report that the container does not exist. Cosmos throttles with 429 routinely, so this is not only a theoretical case.The same connector already answers the equivalent question for the database correctly:
collection_existsmakes the same call against the container, with a broader catch and no second branch.I flagged this in #14510, which makes the same change for the Chroma connector.
Description
collection_existsnow mirrors_does_database_exist:CosmosResourceNotFoundErrorreturnsFalse, and anything else is raised asVectorStoreOperationExceptionwith the container name in the message.CosmosResourceNotFoundErrorwas already imported in this file.One thing worth knowing, outside this change:
VectorStore.collection_existsindata/vector.pywraps this method and converts aVectorStoreOperationExceptiontoFalse. So at the store level a failure still reads as absent. That is the framework wrapper's own choice, and I have left it alone here.Contribution Checklist
Three unit tests, none existed for
collection_existson this collection. A missing container returnsFalse, a 429 raises, and a successful read returnsTrue.Against unmodified
mainthe 429 test fails and the other two pass, so the change cannot turn a missing container or a present one into an error.