chroma-core/chroma · error · ValueError
ids must be provided for transactional delete
Error message
ids must be provided for transactional delete
What it means
Raised by AsyncConditionalCollectionTransaction.delete(). Conditional (optimistic) transactions only support delete-by-ID: the wrapper builds the delete request with where/where_document forced to None, then requires the validated 'ids' field to be non-None. Predicate deletes are an explicit limitation of the transaction API, so any ids value that unpacks to None is rejected before the server is called.
Source
Thrown at chromadb/api/models/AsyncConditionalCollectionTransaction.py:258
self._collection._client._conditional_upsert(
transaction=self._transaction,
collection_id=self._collection.id,
ids=upsert_request["ids"],
embeddings=upsert_request["embeddings"],
metadatas=upsert_request["metadatas"],
documents=upsert_request["documents"],
uris=upsert_request["uris"],
tenant=self._collection.tenant,
database=self._collection.database,
)
)
async def delete(self, ids: OneOrMany[ID]) -> None:
delete_request = self._collection._validate_and_prepare_delete_request(
ids, None, None
)
if delete_request["ids"] is None:
raise ValueError("ids must be provided for transactional delete")
await self._run_transaction_operation(
self._collection._client._conditional_delete(
transaction=self._transaction,
collection_id=self._collection.id,
ids=delete_request["ids"],
tenant=self._collection.tenant,
database=self._collection.database,
)
)
async def commit(self) -> ConditionalCommitResult:
if self._commit_blocked_by_run:
raise ValueError("txn.commit() cannot be called inside run()")
return await self._commit_after_run()
View on GitHub (pinned to aecdd12c8a)
Solutions
- Pass an explicit list of concrete string IDs: `await txn.delete(["id-1", "id-2"])`
- If you need delete-by-filter, first `txn.get(where=..., include=[])` inside the transaction to collect IDs, then delete those IDs in the same transaction
- If predicate semantics are required and transactional guarantees are not, use the non-transactional `collection.delete(where=..., where_document=...)`
- Check the ids variable is a non-empty list before entering `run()`
Example fix
// before
await txn.delete(ids=None) # or a variable that is None at runtime
// after
if not ids:
raise ValueError("cannot delete without ids inside a transaction")
await txn.delete(ids=ids) Defensive patterns
Strategy: validation
Validate before calling
ids = ["a", "b"]
if ids is None or len(list(ids)) == 0:
raise ValueError("transactional delete requires explicit non-empty ids")
await txn.delete(ids=list(ids)) Type guard
from typing import Any, List, TypeGuard
def is_non_empty_id_list(v: Any) -> TypeGuard[List[str]]:
return isinstance(v, (list, tuple)) and len(v) > 0 and all(isinstance(i, str) for i in v) Prevention
- Never pass where/where_document semantics into txn.delete; transactions are delete-by-id only
- Resolve filter-based deletes to an explicit id list with txn.get(where=..., include=[]) before deleting
- Assert ids are non-empty right before the delete call inside the run callback
When it happens
Trigger: Calling `await txn.delete(ids)` on a transaction obtained from an AsyncCollection where `ids` survives the 'at least one parameter' presence check but validates/unpacks to a None ids list (e.g. a None-equivalent or empty/malformed value passed through maybe_cast_one_to_many).
Common situations: Porting `collection.delete(where=...)` / `delete(where_document=...)` calls into `collection.transaction.run(...)`, or passing a variable that is None at runtime inside the run callback.
Related errors
- ids must be provided for transactional delete
- txn.commit() cannot be called inside run()
- At least one of ids, where, or where_document must be provid
- max_retries must be a non-negative integer
- Knn limit must be a positive integer
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/79adb91414ecd332.
Report an issue: GitHub.