mem0ai/mem0 · error · Exception

Delete failed for document {vector_id}: {doc}

Error message

Delete failed for document {vector_id}: {doc}

What it means

Raised by AzureAISearch.delete after search_client.delete_documents returns a non-success response for the given vector_id. Deletion fails when the document does not exist under that exact id, the id contains characters the index key rejects, the credential lacks delete permissions, or the service is throttling. As with insert, the guard only fires for dict-like responses without a status_code attribute, so a raise here reflects a real server-side rejection reported in the doc dict.

Source

Thrown at mem0/vector_stores/azure_ai_search.py:294

        )

        results = []
        for result in search_results:
            payload = json.loads(extract_json(result["payload"]))
            results.append(OutputData(id=result["id"], score=result["@search.score"], payload=payload))
        return results

    def delete(self, vector_id):
        """
        Delete a vector by ID.

        Args:
            vector_id (str): ID of the vector to delete.
        """
        response = self.search_client.delete_documents(documents=[{"id": vector_id}])
        for doc in response:
            if not hasattr(doc, "status_code") and doc.get("status_code") != 200:
                raise Exception(f"Delete failed for document {vector_id}: {doc}")
        logger.info(f"Deleted document with ID '{vector_id}' from index '{self.index_name}'.")
        return response

    def update(self, vector_id, vector=None, payload=None):
        """
        Update a vector and its payload.

        Args:
            vector_id (str): ID of the vector to update.
            vector (List[float], optional): Updated vector.
            payload (Dict, optional): Updated payload.
        """
        document = {"id": vector_id}
        if vector is not None:
            document["vector"] = vector
        if payload is not None:
            json_payload = json.dumps(payload)
            document["payload"] = json_payload

View on GitHub (pinned to 001c235229)

Solutions

  1. Inspect the doc dict in the exception for the HTTP status (404 → already gone, 403 → permissions, 429 → throttle)
  2. Make delete idempotent: catch the error, verify with get(vector_id) that it is gone, and treat 404 as success
  3. Check the API key/RBAC has Documents.Read/Write (delete) on the index
  4. For races, deduplicate delete requests by id before dispatching

Example fix

# before
memory.delete(memory_id)  # Delete failed for document ...

# after
def safe_delete(memory, memory_id):
    try:
        memory.delete(memory_id)
    except Exception:
        if memory.get(memory_id) is None:
            return  # already gone
        raise
Defensive patterns

Strategy: try-catch

Validate before calling

def delete_is_safe(memory, memory_id) -> bool:
    return memory.get(memory_id) is not None  # skip no-op deletes

Try / catch

try:
    memory.delete(memory_id)
except Exception as e:
    if 'Delete failed for document' in str(e):
        if memory.get(memory_id) is None:
            return  # idempotent success
        raise
    raise

Prevention

When it happens

Trigger: Calling memory.delete(memory_id) where the memory was already deleted or its id was reformatted; concurrent deletes racing each other; API-key scoped to read-only; index recreated so old ids no longer exist.

Common situations: Retrying an already-completed delete from a queue consumer; id mismatch after migrating stores; RBAC/Key permissions missing the delete action.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/b242aa50abb74bc2. Report an issue: GitHub.