chroma-core/chroma · error · ValueError
limit must be a non-negative integer
Error message
limit must be a non-negative integer
What it means
collection.delete(..., limit=n) caps how many matched records are deleted. SegmentAPI re-validates limit defensively ('validated upstream, but enforce defensively'): it must be a real int (bool is explicitly rejected, since isinstance(True, int) is True in Python) and non-negative. Violations raise ValueError('limit must be a non-negative integer').
Source
Thrown at chromadb/api/segment.py:807
tenant=tenant,
ids=ids,
where=where,
where_document=where_document,
)
self._manager.hint_use_collection(collection_id, t.Operation.DELETE)
if (where or where_document) or not ids:
ids_to_delete = self._executor.get(
GetPlan(scan, Filter(ids, where, where_document))
)["ids"]
else:
ids_to_delete = ids
# Apply limit if specified (validated upstream, but enforce defensively)
if limit is not None:
if not isinstance(limit, int) or isinstance(limit, bool) or limit < 0:
raise ValueError("limit must be a non-negative integer")
if where is None and where_document is None:
raise ValueError(
"limit can only be specified when a where or where_document clause is provided"
)
ids_to_delete = ids_to_delete[:limit]
if len(ids_to_delete) == 0:
return DeleteResult(deleted=0)
records_to_submit = list(
_records(operation=t.Operation.DELETE, ids=ids_to_delete)
)
self._validate_embedding_record_set(scan.collection, records_to_submit)
self._producer.submit_embeddings(collection_id, records_to_submit)
deleted_count = len(ids_to_delete)
self._product_telemetry_client.capture(View on GitHub (pinned to aecdd12c8a)
Solutions
- Normalize before the call: cast to int, reject bools, require >= 0 — or pass None to skip limiting
- Use None instead of -1/0-style sentinels when you mean 'no limit'
- Validate kwargs once in a wrapper so every delete path gets a clean limit
Example fix
// before
n = request.args.get('limit', -1) # arrives as '-1' or -1
coll.delete(where=f, limit=n)
// after
raw = request.args.get('limit')
n = int(raw) if raw is not None else None
assert n is None or (isinstance(n, int) and not isinstance(n, bool) and n >= 0)
coll.delete(where=f, limit=n) Defensive patterns
Strategy: validation
Validate before calling
def normalize_delete_limit(value):
if value is None:
return None
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
raise ValueError(f'limit must be a non-negative int, got {value!r}')
return value
coll.delete(where=f, limit=normalize_delete_limit(raw_limit)) Type guard
def is_valid_delete_limit(v) -> bool:
return v is None or (isinstance(v, int) and not isinstance(v, bool) and v >= 0) Prevention
- Cast and bound user-supplied limits at the API boundary (int(...) with try/except)
- Remember bool is a subclass of int in Python — reject it explicitly
- Use None for 'no limit', never -1
When it happens
Trigger: coll.delete(where=..., limit=-1), limit=2.5, limit='10' (string from JSON/query params), or limit=True — any bool, non-int, or negative value passed as limit.
Common situations: Forwarding untyped user input (HTTP query params, config files) straight into limit; using -1 as an 'unlimited' sentinel carried over from SQL habits; JSON configs where numbers deserialize as strings.
Related errors
- limit can only be specified when a where or where_document c
- Limit offset must be a non-negative integer
- Limit must be a positive integer when provided
- Invalid limit input
- limit must be a non-negative integer
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/703f54d8df9bf9b0.
Report an issue: GitHub.