{"record":{"id":"28733688be42a8a5","repo":"chroma-core/chroma","slug":"knn-key-must-be-a-string-got-type-key-name","errorCode":null,"errorMessage":"$knn key must be a string, got {type(key).__name__}","messagePattern":"\\$knn key must be a string, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"chromadb/execution/expression/operator.py","lineNumber":727,"sourceCode":"            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(\n                    f\"$knn return_rank must be a boolean, got {type(return_rank).__name__}\"\n                )\n\n            return Knn(\n                query=query,\n                key=key,","sourceCodeStart":709,"sourceCodeEnd":745,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/chromadb/execution/expression/operator.py#L709-L745","documentation":"The optional 'key' field of $knn names the vector column to search (default '#embedding') and must be a string. Non-string keys - int, None, list - raise TypeError. Named keys matter in collections that store multiple embeddings per record.","triggerScenarios":"{'$knn': {'query': emb, 'key': 0}}; {'key': None}; {'key': ['#embedding']} with the name wrapped in a list; forwarding an int column index from a 'search field N' API.","commonSituations":"Supporting numeric column selectors and forwarding the index; form/query-string parsers producing lists ('?key=a,b'); configs distinguishing absent vs explicitly-null keys.","solutions":["Pass the column name as a string: {'key': '#embedding'}.","Omit 'key' entirely to use the default.","Map numeric column selectors to their string names before building the expression."],"exampleFix":"# before\nSearch(rank={'$knn': {'query': emb, 'key': 0}})   # -> TypeError: got int\n\n# after\nSearch(rank={'$knn': {'query': emb, 'key': '#embedding'}})","handlingStrategy":"validation","validationCode":"key = knn_opts.get('key', '#embedding')\nif not isinstance(key, str):\n    raise TypeError(f'$knn key must be a string, got {type(key).__name__}')\nSearch(rank={'$knn': {'query': emb, 'key': key}})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Vector keys are names (strings), not indices - '#embedding' is the default column.","Keep 'key' optional: omit it unless you use named vector columns.","Beware query-string params that arrive as lists; take the single element or reject."],"tags":["validation","typeerror","knn","key","chromadb"],"backgroundTag":"type-validation-failed","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}