{"record":{"id":"0b3d0ed0e9df3ea3","repo":"headroomlabs-ai/headroom","slug":"query-text-provided-but-hnswvectorindex-does-not-e","errorCode":null,"errorMessage":"query_text provided but HNSWVectorIndex does not embed text. Provide query_vector directly or use an Embedder first.","messagePattern":"query_text provided but HNSWVectorIndex does not embed text\\. Provide query_vector directly or use an Embedder first\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/memory/adapters/hnsw.py","lineNumber":591,"sourceCode":"\n        return removed_count\n\n    async def search(self, filter: VectorFilter) -> list[VectorSearchResult]:\n        \"\"\"Search for similar memories using vector similarity.\n\n        Args:\n            filter: Vector search filter with query and constraints.\n\n        Returns:\n            List of search results sorted by similarity (descending).\n\n        Raises:\n            ValueError: If neither query_vector nor query_text is provided,\n                       or if query_text is provided (embedding must be done externally).\n        \"\"\"\n        if filter.query_vector is None:\n            if filter.query_text is not None:\n                raise ValueError(\n                    \"query_text provided but HNSWVectorIndex does not embed text. \"\n                    \"Provide query_vector directly or use an Embedder first.\"\n                )\n            raise ValueError(\"Either query_vector or query_text must be provided\")\n\n        query_vector = np.asarray(filter.query_vector, dtype=np.float32)\n        if query_vector.shape[0] != self._dimension:\n            raise ValueError(\n                f\"Query vector dimension {query_vector.shape[0]} does not match \"\n                f\"index dimension {self._dimension}\"\n            )\n\n        with self._lock:\n            # NOTE: Use len() directly, not self.size - Lock is not reentrant!\n            current_size = len(self._memory_to_hnsw)\n            if current_size == 0:\n                return []\n","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/memory/adapters/hnsw.py#L573-L609","documentation":"Raised by HNSWVectorIndex.search when VectorFilter.query_vector is None but query_text is set. HNSWVectorIndex is a pure vector index with no built-in text embedding, so it cannot convert text to a vector; the caller must embed the text first or pass a query_vector.","triggerScenarios":"Calling search(VectorFilter(query_text=\"...\")) directly on HNSWVectorIndex instead of going through a higher-level component that owns an Embedder; porting code from an index that did support text queries.","commonSituations":"Assuming all VectorIndex implementations embed text; wiring a raw index into a search path without an embedding step; misreading the filter schema.","solutions":["Embed the text first: vec = await embedder.embed(filter.query_text), then search with VectorFilter(query_vector=vec).","Use a facade/service that pairs an Embedder with the index and accepts text queries.","If you never need text search, ensure only query_vector is ever set on the filter."],"exampleFix":"// before\nresults = await index.search(VectorFilter(query_text=\"hello\"))\n\n// after\nvec = await embedder.embed(\"hello\")\nresults = await index.search(VectorFilter(query_vector=vec))","handlingStrategy":"validation","validationCode":"if filter.query_vector is None and filter.query_text is not None:\n    filter.query_vector = await embedder.embed(filter.query_text)\n    filter.query_text = None\nresults = await index.search(filter)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep an Embedder next to the index in one service and always hand vectors to raw indexes.","Document per-backend whether query_text is supported."],"tags":["hnsw","search","query-text","validation"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}