chroma-core/chroma · error · ValueError

Invalid task: {self.query_config.get('task')}

Error message

Invalid task: {self.query_config.get('task')}

What it means

In embed_query, when query_config is provided it is dispatched on query_config.get('task'): 'document' → encode_document, 'query' → encode_query. A query_config dict that is missing the 'task' key (get returns None) or carries an unrecognized value raises ValueError(f"Invalid task: {query_config.get('task')}"). The expected shape is the TypedDict HuggingFaceSparseEmbeddingFunctionQueryConfig = {'task': Literal['document','query']}.

Source

Thrown at chromadb/utils/embedding_functions/huggingface_sparse_embedding_function.py:128

    def embed_query(self, input: Documents) -> SparseVectors:
        try:
            from sentence_transformers import SparseEncoder
        except ImportError:
            raise ValueError(
                "The sentence_transformers python package is not installed. Please install it with `pip install sentence_transformers`"
            )
        model = cast(SparseEncoder, self._model)
        if self.query_config is not None:
            if self.query_config.get("task") == "document":
                embeddings = model.encode_document(
                    list(input),
                )
            elif self.query_config.get("task") == "query":
                embeddings = model.encode_query(
                    list(input),
                )
            else:
                raise ValueError(f"Invalid task: {self.query_config.get('task')}")

            sparse_vectors: SparseVectors = []

            for vec in embeddings:
                # Convert sparse tensor to dense array if needed
                if hasattr(vec, "to_dense"):
                    vec_dense = vec.to_dense().numpy()
                else:
                    vec_dense = vec.numpy() if hasattr(vec, "numpy") else np.array(vec)

                nz = np.where(vec_dense != 0)[0]
                sparse_vectors.append(
                    normalize_sparse_vector(
                        indices=nz.tolist(), values=vec_dense[nz].tolist()
                    )
                )

            return sparse_vectors

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Always include a valid 'task' key: query_config={'task': 'query'}
  2. Pass query_config=None (the default) to make embed_query reuse the top-level task setting
  3. Validate before constructing: assert set(('task',)) <= query_config.keys() and query_config['task'] in ('document', 'query')

Example fix

# before
ef = HuggingFaceSparseEmbeddingFunction(
    model_name="prithivida/Splade_PP_en_v1", device="cpu", task="document",
    query_config={"model": "x"},  # no "task" key -> "Invalid task: None"
)

# after
ef = HuggingFaceSparseEmbeddingFunction(
    model_name="prithivida/Splade_PP_en_v1", device="cpu", task="document",
    query_config={"task": "query"},
)
Defensive patterns

Strategy: validation

Validate before calling

def build_query_config(cfg: dict | None):
    if cfg is None:
        return None
    task = cfg.get("task")
    if task not in ("document", "query"):
        raise ValueError(
            f"query_config['task'] must be 'document' or 'query', got {task!r}"
        )
    return {"task": task}

ef = HuggingFaceSparseEmbeddingFunction(
    model_name="prithivida/Splade_PP_en_v1",
    device="cpu",
    task="document",
    query_config=build_query_config(user_cfg),
)

Type guard

from typing import TypedDict, Literal

class QueryConfig(TypedDict):
    task: Literal["document", "query"]

def is_valid_query_config(c: object) -> bool:
    return (
        isinstance(c, dict)
        and set(c) >= {"task"}
        and c["task"] in ("document", "query")
    )

Try / catch

try:
    ef.embed_query(["q"])
except ValueError as e:
    if str(e).startswith("Invalid task:"):
        raise ValueError("query_config must contain task='document'|'query'") from e
    raise

Prevention

When it happens

Trigger: Passing query_config={} (empty dict) or query_config={'task': 'querys'}/{'task': None} to the constructor and then calling embed_query/collection.query; passing extra keys alongside a missing 'task'; reusing a Nomic-style query config whose task values are 'search_query' rather than 'query'.

Common situations: Building query_config dynamically (e.g. from user settings) where 'task' can be absent; migrating configs between Nomic (search_document/search_query vocabulary) and HuggingFace sparse ('document'/'query'); treating query_config as optional-metadata dict instead of a required-key TypedDict.

Related errors


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