chroma-core/chroma · error · NotImplementedError

AsyncClient cannot be created synchronously. Use .from_syste

Error message

AsyncClient cannot be created synchronously. Use .from_system_async() instead.

What it means

SharedSystemClient.from_system is a synchronous construction contract, but AsyncClient needs an awaited initialization, so its override raises NotImplementedError and directs you to the async classmethod from_system_async (chromadb/api/async_client.py:112-126). Any generic factory that calls cls.from_system(system) on whatever client class it was handed will trip this.

Source

Thrown at chromadb/api/async_client.py:124

    @classmethod
    # (we can't override and use from_system() because it's synchronous)
    async def from_system_async(
        cls,
        system: System,
        tenant: str = DEFAULT_TENANT,
        database: str = DEFAULT_DATABASE,
    ) -> "AsyncClient":
        """Create a client from an existing system. This is useful for testing and debugging."""
        return await AsyncClient.create(tenant, database, system.settings)

    @classmethod
    @override
    def from_system(
        cls,
        system: System,
    ) -> "SharedSystemClient":
        """AsyncClient cannot be created synchronously. Use .from_system_async() instead."""
        raise NotImplementedError(
            "AsyncClient cannot be created synchronously. Use .from_system_async() instead."
        )

    @override
    async def get_user_identity(self) -> UserIdentity:
        return await self._server.get_user_identity()

    @override
    async def set_tenant(self, tenant: str, database: str = DEFAULT_DATABASE) -> None:
        await self._validate_tenant_database(tenant=tenant, database=database)
        self.tenant = tenant
        self.database = database

    @override
    async def set_database(self, database: str) -> None:
        await self._validate_tenant_database(tenant=self.tenant, database=database)
        self.database = database

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Use the async path: await AsyncClient.from_system_async(system)
  2. Branch in shared factories: use from_system_async for AsyncClient, from_system for the sync Client
  3. For normal usage prefer AsyncHttpClient(...) instead of manually building a System

Example fix

# before
client = AsyncClient.from_system(system)  # NotImplementedError

# after
client = await AsyncClient.from_system_async(system)
Defensive patterns

Strategy: type-guard

Validate before calling

from chromadb.api.async_client import AsyncClient

async def client_from_system(cls, system):
    if isinstance(cls, type) and issubclass(cls, AsyncClient):
        return await cls.from_system_async(system)
    return cls.from_system(system)

Type guard

from chromadb.api.async_client import AsyncClient

def is_async_client_class(cls) -> bool:
    """True when cls must be constructed via from_system_async (awaited)."""
    return isinstance(cls, type) and issubclass(cls, AsyncClient)

Try / catch

try:
    client = SomeClient.from_system(system)
except NotImplementedError as e:
    if 'from_system_async' in str(e):
        client = await AsyncClient.from_system_async(system)
    else:
        raise

Prevention

When it happens

Trigger: AsyncClient.from_system(system); System-based factory or registry code that treats Client and AsyncClient uniformly; test fixtures copied from the sync client.

Common situations: Libraries wrapping both the sync and async clients behind one create function; incremental migration of sync code to asyncio.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/eaa26afb5f5828b0. Report an issue: GitHub.