microsoft/semantic-kernel · error · ServiceResponseException

Upsert failed

Error message

Upsert failed

What it means

Raised by QdrantMemoryStore.upsert() when the Qdrant client returns a result whose status is not UpdateStatus.COMPLETED. It is a ServiceResponseException; the upsert may have been acknowledged but not confirmed within the wait window. Note upsert() does not check collection existence first, so an absent collection usually surfaces as a client error before reaching this line.

Source

Thrown at python/semantic_kernel/connectors/memory_stores/qdrant/qdrant_memory_store.py:100

    @override
    async def does_collection_exist(self, collection_name: str) -> bool:
        return self._qdrantclient.collection_exists(collection_name=collection_name)

    @override
    async def upsert(self, collection_name: str, record: MemoryRecord) -> str:
        data_to_upsert = await self._convert_from_memory_record(
            collection_name=collection_name,
            record=record,
        )

        result = self._qdrantclient.upsert(
            collection_name=collection_name,
            points=[data_to_upsert],
        )

        if result.status == qdrant_models.UpdateStatus.COMPLETED:
            return data_to_upsert.id
        raise ServiceResponseException("Upsert failed")

    @override
    async def upsert_batch(self, collection_name: str, records: list[MemoryRecord]) -> list[str]:
        tasks = []
        for record in records:
            tasks.append(
                self._convert_from_memory_record(
                    collection_name=collection_name,
                    record=record,
                )
            )

        data_to_upsert = await asyncio.gather(*tasks)

        result = self._qdrantclient.upsert(
            collection_name=collection_name,
            points=data_to_upsert,
        )

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Retry the upsert with exponential backoff for transient non-COMPLETED statuses.
  2. Configure the QdrantClient for synchronous confirmation (so status reflects actual completion).
  3. Reduce batch/point size or warm the collection before bulk upserts.
  4. Catch ServiceResponseException, log result.status, and decide retry vs fail.

Example fix

// before
key = await store.upsert('mycol', record)
// after
from semantic_kernel.exceptions import ServiceResponseException
for attempt in range(3):
    try:
        key = await store.upsert('mycol', record)
        break
    except ServiceResponseException:
        if attempt == 2: raise
        await asyncio.sleep(2 ** attempt)
Defensive patterns

Strategy: retry

Try / catch

from semantic_kernel.exceptions import ServiceResponseException
for attempt in range(3):
    try:
        key = await store.upsert(collection_name, record)
        break
    except ServiceResponseException:
        if attempt == 2:
            raise
        await asyncio.sleep(2 ** attempt)

Prevention

When it happens

Trigger: Calling `await store.upsert(collection_name, record)` where self._qdrantclient.upsert(...) returns status ACKNOWLEDGED (or any non-COMPLETED value), e.g. when the client is configured with wait=False or the operation times out before confirmation.

Common situations: QdrantClient created without wait=True semantics; heavy load causing the operation to be acknowledged but not completed within the timeout; transient network issues; very large point payloads.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/ef605e15e4616731. Report an issue: GitHub.