{"record":{"id":"204a93aff496b61d","repo":"chroma-core/chroma","slug":"knn-query-must-be-a-list-numpy-array-or-sparsev","errorCode":null,"errorMessage":"$knn query must be a list, numpy array, or SparseVector dict, got {type(query).__name__}","messagePattern":"\\$knn query must be a list, numpy array, or SparseVector dict, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":721,"sourceCode":"                else:\n                    # Old format or invalid - try to construct directly\n                    raise ValueError(\n                        f\"Expected dict with {TYPE_KEY}='{SPARSE_VECTOR_TYPE_VALUE}', got {query}\"\n                    )\n\n            elif isinstance(query, (list, tuple, np.ndarray)):\n                # Dense vector case - normalize then validate\n                normalized = normalize_embeddings(query)\n                if not normalized or len(normalized) > 1:\n                    raise ValueError(\"$knn requires exactly one query embedding\")\n\n                # Validate the normalized version\n                validate_embeddings(normalized)\n\n                query = normalized[0]\n\n            else:\n                raise TypeError(\n                    f\"$knn query must be a list, numpy array, or SparseVector dict, got {type(query).__name__}\"\n                )\n\n            key = knn_data.get(\"key\", \"#embedding\")\n            if not isinstance(key, str):\n                raise TypeError(f\"$knn key must be a string, got {type(key).__name__}\")\n\n            limit = knn_data.get(\"limit\", 16)\n            if not isinstance(limit, int):\n                raise TypeError(\n                    f\"$knn limit must be an integer, got {type(limit).__name__}\"\n                )\n            if limit <= 0:\n                raise ValueError(f\"$knn limit must be positive, got {limit}\")\n\n            return_rank = knn_data.get(\"return_rank\", False)\n            if not isinstance(return_rank, bool):\n                raise TypeError(","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L703-L739","documentation":"$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.","triggerScenarios":"{'$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.","commonSituations":"Assuming $knn embeds text server-side; optional embeddings defaulting to None; double-wrapping vectors in dicts when adapting another API's payload shape.","solutions":["Embed first, then query: {'$knn': {'query': embedding_function([text])[0]}}.","Unwrap extra dict layers so the sequence itself is the query.","If the embedding is None/unavailable, do not issue the ranked query."],"exampleFix":"# before\nSearch(rank={'$knn': {'query': 'hello world'}})   # -> TypeError: got str\n\n# after\nemb = embedding_function(['hello world'])[0]\nSearch(rank={'$knn': {'query': emb}})","handlingStrategy":"type-guard","validationCode":"def is_queryable_embedding(q) -> bool:\n    return isinstance(q, (list, tuple)) or isinstance(q, np.ndarray)\n\nif not is_queryable_embedding(q):\n    q = embedding_function([q])[0]   # embed raw text before searching\nSearch(rank={'$knn': {'query': q}})","typeGuard":"def is_knn_query(q) -> bool:\n    if isinstance(q, (list, tuple, np.ndarray)):\n        return True                                   # dense\n    return isinstance(q, dict) and q.get('#type') == 'sparse_vector'  # sparse","tryCatchPattern":null,"preventionTips":["$knn never embeds strings - run your embedding function first.","Assert the query variable is a vector (or tagged sparse dict) before building the payload.","Fail loudly when the embedding service returns None instead of forwarding it."],"tags":["validation","typeerror","knn","embedding","chromadb"],"backgroundTag":"type-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}