Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ target/

# Rapid test data
testdata
sql-test-repo
15 changes: 15 additions & 0 deletions chromadb/api/async_fastapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import orjson
from typing import Any, Mapping, Optional, cast, Tuple, Sequence, Dict, List
import logging
import warnings
import httpx
from overrides import override
from chromadb import __version__
Expand Down Expand Up @@ -791,6 +792,20 @@ async def reset(self) -> bool:
resp_json = await self._make_request("post", "/reset")
return cast(bool, resp_json)

async def _check_version_compatibility(self) -> None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

[Logic] _check_version_compatibility is an async method but AsyncFastAPI.__init__ is synchronous — Python __init__ cannot await coroutines. As written, this method is never called during construction of the async client (there is no self._check_version_compatibility() call in AsyncFastAPI.__init__). The version check is completely inoperative for the async client.

To invoke this on startup, it would need to be called from an async entry point such as __aenter__ or a factory create() classmethod. For example:

async def __aenter__(self) -> "AsyncFastAPI":
    self._get_client()
    await self._check_version_compatibility()
    return self

Alternatively, expose a synchronous wrapper or document that callers must invoke it manually after await-ing construction.

Context for Agents
`_check_version_compatibility` is an `async` method but `AsyncFastAPI.__init__` is synchronous — Python `__init__` cannot `await` coroutines. As written, this method is never called during construction of the async client (there is no `self._check_version_compatibility()` call in `AsyncFastAPI.__init__`). The version check is completely inoperative for the async client.

To invoke this on startup, it would need to be called from an async entry point such as `__aenter__` or a factory `create()` classmethod. For example:
```python
async def __aenter__(self) -> "AsyncFastAPI":
    self._get_client()
    await self._check_version_compatibility()
    return self
```
Alternatively, expose a synchronous wrapper or document that callers must invoke it manually after `await`-ing construction.

File: chromadb/api/async_fastapi.py
Line: 798

"""Warn if client and server major.minor versions differ."""
try:
server_version = await self.get_version()
if server_version.split(".")[:2] != __version__.split(".")[:2]:
warnings.warn(
f"Chroma client version ({__version__}) may not be compatible "
f"with server version ({server_version}). "
f"Please ensure client and server use the same major.minor version.",
stacklevel=2,
)
except Exception as e:
logger.debug("Version compatibility check failed", exc_info=e)

@trace_method("AsyncFastAPI.get_version", OpenTelemetryGranularity.OPERATION)
@override
async def get_version(self) -> str:
Expand Down
18 changes: 18 additions & 0 deletions chromadb/api/fastapi.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import orjson
import logging
import warnings
from typing import Any, Dict, Mapping, Optional, cast, Tuple, List
from typing import Sequence
from uuid import UUID
Expand Down Expand Up @@ -107,6 +108,7 @@ def __init__(self, system: System):
_headers = self._auth_provider.authenticate()
for header, value in _headers.items():
self._session.headers[header] = value.get_secret_value()
self._check_version_compatibility()

@override
def get_request_headers(self) -> Mapping[str, str]:
Expand Down Expand Up @@ -773,6 +775,22 @@ def reset(self) -> bool:
resp_json = self._make_request("post", "/reset")
return cast(bool, resp_json)

def _check_version_compatibility(self) -> None:
"""Warn if client and server major.minor versions differ."""
try:
resp = self._session.get(self._api_url + "/version", timeout=5.0)
resp.raise_for_status()
server_version = resp.json()
if server_version.split(".")[:2] != __version__.split(".")[:2]:
warnings.warn(
f"Chroma client version ({__version__}) may not be compatible "
f"with server version ({server_version}). "
f"Please ensure client and server use the same major.minor version.",
stacklevel=3,
)
except Exception as e:
logger.debug("Version compatibility check failed", exc_info=e)

@trace_method("FastAPI.get_version", OpenTelemetryGranularity.OPERATION)
@override
def get_version(self) -> str:
Expand Down