chroma-core/chroma · error · BatchSizeExceededError

BatchSizeExceededError

BatchSizeExceededError

Error message

Cannot submit more than {max_batch_size:,} embeddings at once.
Please submit your embeddings in batches of size
{max_batch_size:,} or less.

What it means

submit_embeddings enforces a hard cap: if len(embeddings) exceeds max_batch_size, chromadb.errors.BatchSizeExceededError is raised and nothing is written (chromadb/db/mixins/embeddings_queue.py:199). The cap is derived from SQLite's compiled MAX_VARIABLE_NUMBER pragma limit divided by VARIABLES_PER_RECORD (fallback 999 // VARIABLES_PER_RECORD), because each record binds many SQL parameters in one statement.

Source

Thrown at chromadb/db/mixins/embeddings_queue.py:199

    ) -> SeqId:
        if not self._running:
            raise RuntimeError("Component not running")

        return self.submit_embeddings(collection_id, [embedding])[0]

    @trace_method("SqlEmbeddingsQueue.submit_embeddings", OpenTelemetryGranularity.ALL)
    @override
    def submit_embeddings(
        self, collection_id: UUID, embeddings: Sequence[OperationRecord]
    ) -> Sequence[SeqId]:
        if not self._running:
            raise RuntimeError("Component not running")

        if len(embeddings) == 0:
            return []

        if len(embeddings) > self.max_batch_size:
            raise BatchSizeExceededError(
                f"""
                Cannot submit more than {self.max_batch_size:,} embeddings at once.
                Please submit your embeddings in batches of size
                {self.max_batch_size:,} or less.
                """
            )

        # This creates the persisted configuration if it doesn't exist.
        # It should be run as soon as possible (before any WAL mutations) since the default configuration depends on the WAL size.
        # (We can't run this in __init__()/start() because the migrations have not been run at that point and the table may not be available.)
        _ = self.config

        topic_name = create_topic_name(
            self._tenant, self._topic_namespace, collection_id
        )

        t = Table("embeddings_queue")
        insert = (

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Chunk submissions to at most queue.max_batch_size records per call (read the property; do not hardcode).
  2. If you control the deployment, use a SQLite build with a higher MAX_VARIABLE_NUMBER (modern builds default to 32766/250000), which raises the cap automatically.
  3. Keep public client max_batch_size settings aligned with (not above) the queue's derived limit.

Example fix

# before
seq_ids = queue.submit_embeddings(collection_id, records)  # BatchSizeExceededError if too large

# after
step = queue.max_batch_size
seq_ids: list = []
for i in range(0, len(records), step):
    seq_ids.extend(queue.submit_embeddings(collection_id, records[i:i + step]))
Defensive patterns

Strategy: validation

Validate before calling

batch = min(len(records), queue.max_batch_size)
seq_ids = []
for i in range(0, len(records), queue.max_batch_size):
    seq_ids.extend(queue.submit_embeddings(collection_id, records[i:i + queue.max_batch_size]))

Type guard

def is_batch_too_large(e: BaseException) -> bool:
    import chromadb.errors
    return isinstance(e, chromadb.errors.BatchSizeExceededError)

Try / catch

from chromadb.errors import BatchSizeExceededError
try:
    queue.submit_embeddings(collection_id, records)
except BatchSizeExceededError:
    step = queue.max_batch_size
    for i in range(0, len(records), step):
        queue.submit_embeddings(collection_id, records[i:i + step])

Prevention

When it happens

Trigger: Submitting more than max_batch_size OperationRecords to the internal SqlEmbeddingsQueue in one call — e.g. a bulk ingestion path that bypasses the client's own batching, or a client max batch size setting raised above what the queue's SQLite limit allows.

Common situations: Bulk-loading large datasets through internal APIs without chunking; custom clients that pass big add() batches straight through; changing the embedding-function or record shape so variables-per-record grows and shrinks the effective cap; older SQLite builds where MAX_VARIABLE_NUMBER is 999 making the cap very small.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/84fd68ac45dd66f6. Report an issue: GitHub.