microsoft/semantic-kernel · error · ServiceResponseException

Batch upsert failed

Error message

Batch upsert failed

What it means

Raised by QdrantMemoryStore.upsert_batch() when the single batched upsert call returns a status other than UpdateStatus.COMPLETED. ServiceResponseException; the whole batch is treated as failed even if only part of it was not confirmed.

Source

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

        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,
        )

        if result.status == qdrant_models.UpdateStatus.COMPLETED:
            return [data.id for data in data_to_upsert]
        raise ServiceResponseException("Batch upsert failed")

    @override
    async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord | None:
        result = await self._get_existing_record_by_payload_id(
            collection_name=collection_name,
            payload_id=key,
            with_embedding=with_embedding,
        )

        if result:
            return MemoryRecord(
                is_reference=result.payload["_is_reference"],
                external_source_name=result.payload["_external_source_name"],
                id=result.payload["_id"],
                description=result.payload["_description"],
                text=result.payload["_text"],
                additional_metadata=result.payload["_additional_metadata"],
                embedding=result.vector,

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Retry the batch, optionally splitting it into smaller chunks to isolate failing points.
  2. Ensure the QdrantClient waits for completion so status is meaningful.
  3. Catch ServiceResponseException and fall back to per-record upsert() for the failed batch.
  4. Cap batch size and add backoff between batches.

Example fix

// before
ids = await store.upsert_batch('mycol', records)
// after
try:
    ids = await store.upsert_batch('mycol', records)
except ServiceResponseException:
    ids = [await store.upsert('mycol', r) for r in records]
Defensive patterns

Strategy: retry

Try / catch

try:
    ids = await store.upsert_batch(collection_name, records)
except ServiceResponseException:
    ids = [await store.upsert(collection_name, r) for r in records]

Prevention

When it happens

Trigger: Calling `await store.upsert_batch(collection_name, records)` where the underlying client upsert of all converted points returns a non-COMPLETED status (ACKNOWLEDGED, timeout).

Common situations: Large batches under load; client not waiting for confirmation; network jitter; collection being resharded/reindexed.

Related errors


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