Skip to content
17 changes: 17 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 @@ -793,6 +794,22 @@ async def reset(self) -> bool:

@trace_method("AsyncFastAPI.get_version", OpenTelemetryGranularity.OPERATION)
@override

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()
from chromadb import __version__ as client_version
if server_version.split(".")[:2] != client_version.split(".")[:2]:
warnings.warn(
f"Chroma client version ({client_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:
pass

async def get_version(self) -> str:
resp_json = await self._make_request("get", "/version")
return cast(str, resp_json)
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 @@ -101,6 +102,7 @@ def __init__(self, system: System):

if self._header is not None:
self._session.headers.update(self._header)
self._check_version_compatibility()

if system.settings.chroma_client_auth_provider:
self._auth_provider = self.require(ClientAuthProvider)
Expand Down Expand Up @@ -775,6 +777,22 @@ def reset(self) -> bool:

@trace_method("FastAPI.get_version", OpenTelemetryGranularity.OPERATION)
@override

def _check_version_compatibility(self) -> None:
"""Warn if client and server major.minor versions differ."""
try:
server_version = self.get_version()
from chromadb import __version__ as client_version
if server_version.split(".")[:2] != client_version.split(".")[:2]:
warnings.warn(
f"Chroma client version ({client_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:
pass

def get_version(self) -> str:
"""Returns the version of the server"""
resp_json = self._make_request("get", "/version")
Expand Down
2 changes: 1 addition & 1 deletion chromadb/server/fastapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,7 @@ def process_query(request: Request, raw_body: bytes) -> QueryResult:
async def pre_flight_checks(self) -> Dict[str, Any]:
def process_pre_flight_checks() -> Dict[str, Any]:
return {
"max_batch_size": self._api.get_max_batch_size(),
"max_batch_size": self._api.get_max_batch_size(), "server_version": chromadb_version,
}

return cast(
Expand Down
Loading