MemPalace/mempalace · error · ValueError
delete requires either ids= or where=
Error message
delete requires either ids= or where=
What it means
Raised by MilvusCollection.delete() (mempalace/backends/milvus.py:798) when the method is called with neither ids= nor where=. delete() is keyword-only and needs at least one selector so it knows which rows to remove; an argumentless delete would otherwise wipe the collection, so the backend refuses instead of guessing.
Source
Thrown at mempalace/backends/milvus.py:798
)
return GetResult(
ids=[str(row.get(FIELD_ID, "")) for row in rows],
documents=[row.get(FIELD_DOCUMENT, "") for row in rows] if spec.documents else [],
metadatas=[self._extract_metadata(row) for row in rows] if spec.metadatas else [],
embeddings=[row.get(FIELD_VECTOR) or [] for row in rows] if spec.embeddings else None,
)
def get_all_metadata(self, where: Optional[dict] = None) -> list[dict]:
rows = self._collect_by_filter(
filter_expr=translate_where(where),
output_fields=[FIELD_ID, FIELD_METADATA],
)
return [self._extract_metadata(row) for row in rows]
def delete(self, *, ids=None, where=None):
filter_expr = translate_where(where)
if ids is None and where is None:
raise ValueError("delete requires either ids= or where=")
if not self._remote_exists():
if self._marker_exists():
raise CollectionNotInitializedError(self._collection_name)
return
if ids is not None and where is not None:
rows = self._collect_by_filter(
filter_expr=filter_expr,
output_fields=[FIELD_ID],
)
allowed = {row[FIELD_ID] for row in rows}
ids = [doc_id for doc_id in ids if doc_id in allowed]
if ids is not None:
if not ids:
return
self._client.delete(collection_name=self._remote_collection, ids=list(ids))
else:
self._client.delete(collection_name=self._remote_collection, filter=filter_expr)
View on GitHub (pinned to 06cb6987f0)
Solutions
- Pass an explicit selector: collection.delete(ids=[...]) or collection.delete(where={...})
- If you build filters dynamically, guard before calling: if ids or where: collection.delete(ids=ids, where=where)
- To delete everything in the collection, use backend.delete_collection() / recreate instead of an argumentless delete
- Remember both parameters are keyword-only: delete(ids=...) not delete([...])
Example fix
// before
collection.delete()
# after
collection.delete(ids=['drawer-42'])
# or
collection.delete(where={'wing': 'projects'}) Defensive patterns
Strategy: validation
Validate before calling
def safe_delete(collection, ids=None, where=None):
if ids is None and where is None:
raise ValueError('refusing to delete without ids or where')
collection.delete(ids=ids, where=where) Type guard
def is_delete_selector(ids, where) -> bool:
return ids is not None or where is not None Try / catch
try:
collection.delete(ids=ids, where=where)
except ValueError as e:
if 'requires either' in str(e):
# build a real selector and retry, never delete blindly
raise Prevention
- Never call delete() bare; always compute a selector first
- Wrap dynamic-filter code: if ids or where: delete(...)
- Treat 'delete everything' as delete_collection, not delete()
When it happens
Trigger: Calling collection.delete() with no arguments, or passing ids/where positionally (they are keyword-only: 'def delete(self, *, ids=None, where=None)'). Also calling delete(ids=[]) is fine, but delete(where={}) with an empty dict: 'where is None' is False so it passes, whereas delete() with both omitted triggers it.
Common situations: Copy-paste from a Chroma-like API where delete is also keyword-only but the caller forgot the filter; refactoring that builds a where clause conditionally and ends up passing None for both; interactive experimentation.
Related errors
- Embedding model mismatch reading palace at {palace_path!r}.
- Milvus filter field {name!r} is not a safe identifier
- $in requires a non-empty list for {field!r}
- $nin requires a non-empty list for {field!r}
- embedding must be a non-empty 1D vector
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/64d0e296701d446b.
Report an issue: GitHub.