mem0ai/mem0 · error · ValueError

Cannot update with an empty vector.

Error message

Cannot update with an empty vector.

What it means

update() in the OpenSearch store refuses an explicitly supplied empty vector (len 0). Unlike None (meaning 'keep existing'), an empty list is a real value that cannot be indexed, so it fails fast before searching for the document. It pairs with the dimension check immediately after it.

Source

Thrown at mem0/vector_stores/opensearch.py:323

        # First, find the document by custom ID
        search_query = {"query": {"term": {"id": vector_id}}}

        response = self.client.search(index=self.collection_name, body=search_query)
        hits = response.get("hits", {}).get("hits", [])

        if not hits:
            return

        opensearch_id = hits[0]["_id"]

        # Delete using the actual document ID
        self.client.delete(index=self.collection_name, id=opensearch_id)

    def update(self, vector_id: str, vector: Optional[List[float]] = None, payload: Optional[Dict] = None) -> None:
        """Update a vector and its payload using the custom 'id' field."""
        if vector is not None:
            if len(vector) == 0:
                raise ValueError("Cannot update with an empty vector.")
            if len(vector) != self.embedding_model_dims:
                raise ValueError(
                    f"Update vector has dimension {len(vector)}, "
                    f"but the index '{self.collection_name}' expects dimension {self.embedding_model_dims}. "
                    f"Ensure your embedding model's output dimensions match the vector store configuration."
                )

        # First, find the document by custom ID
        search_query = {"query": {"term": {"id": vector_id}}}

        response = self.client.search(index=self.collection_name, body=search_query)
        hits = response.get("hits", {}).get("hits", [])

        if not hits:
            return

        opensearch_id = hits[0]["_id"]  # The actual document ID in OpenSearch

View on GitHub (pinned to 001c235229)

Solutions

  1. Pass vector=None when you do not want to change the embedding
  2. If updating the embedding, supply a full-length vector: vector=embed(new_text)
  3. Guard the embedder to raise on empty output instead of returning []

Example fix

# before
store.update(vector_id=vid, vector=[], payload=p)

# after
store.update(vector_id=vid, vector=embed(p["data"]) if p.get("data") else None, payload=p)
Defensive patterns

Strategy: validation

Validate before calling

if vector is not None and len(vector) == 0:
    vector = None  # interpret as 'no embedding change'
store.update(vector_id=vector_id, vector=vector, payload=payload)

Type guard

def is_valid_update_vector(v) -> bool:
    return v is None or (isinstance(v, list) and len(v) > 0)

Try / catch

try:
    store.update(vector_id=vid, vector=vec, payload=p)
except ValueError as e:
    if "empty vector" in str(e):
        store.update(vector_id=vid, vector=None, payload=p)
    else:
        raise

Prevention

When it happens

Trigger: update(vector_id=X, vector=[]) — usually an embedding call that returned an empty list for the new text, or a placeholder that mistakenly defaults to [] instead of None.

Common situations: Re-embedding code paths where the new text is blank; stub/mock embedders returning []; passing [] intending 'no change' when None is required.

Related errors


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