chroma-core/chroma · error · ValueError

Invalid task: {self.task}

Error message

Invalid task: {self.task}

What it means

Bm25EmbeddingFunction dispatches on self.task: "document" calls model.embed() (corpus indexing) and "query" calls model.query_embed() (short queries with different term statistics). Any other value raises this ValueError — but only at call time, because __init__ accepts task without validating it (the type hint is Literal["document", "query"] but hints are not enforced at runtime). The two modes are not interchangeable: indexing with query mode produces vectors incompatible with document embeddings.

Source

Thrown at chromadb/utils/embedding_functions/bm25_embedding_function.py:119

            Embeddings for the documents.
        """
        try:
            from fastembed.sparse.bm25 import Bm25
        except ImportError:
            raise ValueError(
                "The fastembed python package is not installed. Please install it with `pip install fastembed`"
            )
        model = cast(Bm25, self._model)
        if self.task == "document":
            embeddings = model.embed(
                list(input),
            )
        elif self.task == "query":
            embeddings = model.query_embed(
                list(input),
            )
        else:
            raise ValueError(f"Invalid task: {self.task}")

        sparse_vectors: SparseVectors = []

        for vec in embeddings:
            sparse_vectors.append(
                normalize_sparse_vector(
                    indices=vec.indices.tolist(), values=vec.values.tolist()
                )
            )

        return sparse_vectors

    def embed_query(self, input: Documents) -> SparseVectors:
        try:
            from fastembed.sparse.bm25 import Bm25
        except ImportError:
            raise ValueError(
                "The fastembed python package is not installed. Please install it with `pip install fastembed`"

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Use exactly one of the two literals: task="document" when embedding corpus texts, task="query" when embedding search queries.
  2. Validate the value at construction in your own wrapper (see type guard) so the failure surfaces early.
  3. Check ef.get_config()["task"] when debugging a function restored from config.

Example fix

# before: ValueError "Invalid task: doc"
ef = Bm25EmbeddingFunction(task="doc")
index_vectors = ef(corpus)

# after
doc_ef = Bm25EmbeddingFunction(task="document")
query_ef = Bm25EmbeddingFunction(task="query")
index_vectors = doc_ef(corpus)
Defensive patterns

Strategy: type-guard

Validate before calling

VALID_TASKS = {"document", "query"}

def make_bm25_ef(task: str, **kw):
    if task not in VALID_TASKS:
        raise ValueError(f"task must be one of {sorted(VALID_TASKS)}, got {task!r}")
    from chromadb.utils.embedding_functions import Bm25EmbeddingFunction
    return Bm25EmbeddingFunction(task=task, **kw)

Type guard

from typing import Literal

TaskType = Literal["document", "query"]

def is_valid_bm25_task(value: object) -> bool:
    return value in ("document", "query")

Try / catch

try:
    vectors = ef(texts)
except ValueError as e:
    if "Invalid task" in str(e):
        raise RuntimeError("task must be 'document' (corpus) or 'query' (search); got " + str(ef.task)) from e
    raise

Prevention

When it happens

Trigger: Bm25EmbeddingFunction(task="doc") or task="passage" (sentence-transformers convention), then calling ef(texts); also a task injected from an unvalidated config via build_from_config(config.get("task")).

Common situations: Porting retrieval code from sentence-transformers/fastembed conventions where "query"/"passage" is the pairing; typos and casing ("Document"); task read from a YAML/JSON config that was never schema-checked.

Related errors


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