{"record":{"id":"4ab36084c4fd9481","repo":"microsoft/semantic-kernel","slug":"batch-upsert-failed-4ab360","errorCode":null,"errorMessage":"Batch upsert failed","messagePattern":"Batch upsert failed","errorType":"exception","errorClass":"ServiceResponseException","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/memory_stores/qdrant/qdrant_memory_store.py","lineNumber":122,"sourceCode":"        tasks = []\n        for record in records:\n            tasks.append(\n                self._convert_from_memory_record(\n                    collection_name=collection_name,\n                    record=record,\n                )\n            )\n\n        data_to_upsert = await asyncio.gather(*tasks)\n\n        result = self._qdrantclient.upsert(\n            collection_name=collection_name,\n            points=data_to_upsert,\n        )\n\n        if result.status == qdrant_models.UpdateStatus.COMPLETED:\n            return [data.id for data in data_to_upsert]\n        raise ServiceResponseException(\"Batch upsert failed\")\n\n    @override\n    async def get(self, collection_name: str, key: str, with_embedding: bool = False) -> MemoryRecord | None:\n        result = await self._get_existing_record_by_payload_id(\n            collection_name=collection_name,\n            payload_id=key,\n            with_embedding=with_embedding,\n        )\n\n        if result:\n            return MemoryRecord(\n                is_reference=result.payload[\"_is_reference\"],\n                external_source_name=result.payload[\"_external_source_name\"],\n                id=result.payload[\"_id\"],\n                description=result.payload[\"_description\"],\n                text=result.payload[\"_text\"],\n                additional_metadata=result.payload[\"_additional_metadata\"],\n                embedding=result.vector,","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/memory_stores/qdrant/qdrant_memory_store.py#L104-L140","documentation":"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.","triggerScenarios":"Calling `await store.upsert_batch(collection_name, records)` where the underlying client upsert of all converted points returns a non-COMPLETED status (ACKNOWLEDGED, timeout).","commonSituations":"Large batches under load; client not waiting for confirmation; network jitter; collection being resharded/reindexed.","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."],"exampleFix":"// before\nids = await store.upsert_batch('mycol', records)\n// after\ntry:\n    ids = await store.upsert_batch('mycol', records)\nexcept ServiceResponseException:\n    ids = [await store.upsert('mycol', r) for r in records]","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ids = await store.upsert_batch(collection_name, records)\nexcept ServiceResponseException:\n    ids = [await store.upsert(collection_name, r) for r in records]","preventionTips":["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."],"tags":["qdrant","memory-store","upsert","batch","service-response-exception","retry"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}