chroma-core/chroma · error · TypeError

$knn query must be a list, numpy array, or SparseVector dict

Error message

$knn query must be a list, numpy array, or SparseVector dict, got {type(query).__name__}

What it means

$knn's 'query' must be either a dense vector (list/tuple/np.ndarray) or a serialized SparseVector dict. Anything else - string, int, None - raises TypeError. $knn does not embed raw text; the caller must supply the embedding itself.

Source

Thrown at chromadb/execution/expression/operator.py:721

                else:
                    # Old format or invalid - try to construct directly
                    raise ValueError(
                        f"Expected dict with {TYPE_KEY}='{SPARSE_VECTOR_TYPE_VALUE}', got {query}"
                    )

            elif isinstance(query, (list, tuple, np.ndarray)):
                # Dense vector case - normalize then validate
                normalized = normalize_embeddings(query)
                if not normalized or len(normalized) > 1:
                    raise ValueError("$knn requires exactly one query embedding")

                # Validate the normalized version
                validate_embeddings(normalized)

                query = normalized[0]

            else:
                raise TypeError(
                    f"$knn query must be a list, numpy array, or SparseVector dict, got {type(query).__name__}"
                )

            key = knn_data.get("key", "#embedding")
            if not isinstance(key, str):
                raise TypeError(f"$knn key must be a string, got {type(key).__name__}")

            limit = knn_data.get("limit", 16)
            if not isinstance(limit, int):
                raise TypeError(
                    f"$knn limit must be an integer, got {type(limit).__name__}"
                )
            if limit <= 0:
                raise ValueError(f"$knn limit must be positive, got {limit}")

            return_rank = knn_data.get("return_rank", False)
            if not isinstance(return_rank, bool):
                raise TypeError(

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Embed first, then query: {'$knn': {'query': embedding_function([text])[0]}}.
  2. Unwrap extra dict layers so the sequence itself is the query.
  3. If the embedding is None/unavailable, do not issue the ranked query.

Example fix

# before
Search(rank={'$knn': {'query': 'hello world'}})   # -> TypeError: got str

# after
emb = embedding_function(['hello world'])[0]
Search(rank={'$knn': {'query': emb}})
Defensive patterns

Strategy: type-guard

Validate before calling

def is_queryable_embedding(q) -> bool:
    return isinstance(q, (list, tuple)) or isinstance(q, np.ndarray)

if not is_queryable_embedding(q):
    q = embedding_function([q])[0]   # embed raw text before searching
Search(rank={'$knn': {'query': q}})

Type guard

def is_knn_query(q) -> bool:
    if isinstance(q, (list, tuple, np.ndarray)):
        return True                                   # dense
    return isinstance(q, dict) and q.get('#type') == 'sparse_vector'  # sparse

Prevention

When it happens

Trigger: {'$knn': {'query': 'hello world'}} (raw text); {'query': 42}; {'query': None} after a failed embedding call; {'query': {'vector': [...]}} with the list wrapped in an extra dict.

Common situations: Assuming $knn embeds text server-side; optional embeddings defaulting to None; double-wrapping vectors in dicts when adapting another API's payload shape.

Related errors


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