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
- Retry the batch, optionally splitting it into smaller chunks to isolate failing points.
- Ensure the QdrantClient waits for completion so status is meaningful.
- Catch ServiceResponseException and fall back to per-record upsert() for the failed batch.
- 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
- Cap batch size to reduce the blast radius of a non-COMPLETED status.
- Retry failed batches, optionally splitting them.
- Configure the QdrantClient for synchronous completion.
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
- Upsert failed
- Delete failed
- Could not upsert messages.
- Collection '{collection_name}' does not exist
- Error upserting record: {upsert_response.message}
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/4ab36084c4fd9481.
Report an issue: GitHub.