{"record":{"id":"89ace2500b73a3e4","repo":"run-llama/llama_index","slug":"vector-store-query-result-should-return-at-least-o-89ace2","errorCode":null,"errorMessage":"Vector store query result should return at least one of nodes or ids.","messagePattern":"Vector store query result should return at least one of nodes or ids\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/indices/multi_modal/retriever.py","lineNumber":236,"sourceCode":"        self,\n        query_bundle_with_embeddings: QueryBundle,\n        similarity_top_k: int,\n        vector_store: BasePydanticVectorStore,\n    ) -> List[NodeWithScore]:\n        query = self._build_vector_store_query(\n            query_bundle_with_embeddings, similarity_top_k\n        )\n        query_result = vector_store.query(query, **self._kwargs)\n        return self._build_node_list_from_query_result(query_result)\n\n    def _build_node_list_from_query_result(\n        self, query_result: VectorStoreQueryResult\n    ) -> List[NodeWithScore]:\n        if query_result.nodes is None:\n            # NOTE: vector store does not keep text and returns node indices.\n            # Need to recover all nodes from docstore\n            if query_result.ids is None:\n                raise ValueError(\n                    \"Vector store query result should return at \"\n                    \"least one of nodes or ids.\"\n                )\n            assert isinstance(self._index.index_struct, IndexDict)\n            node_ids = [\n                self._index.index_struct.nodes_dict[idx] for idx in query_result.ids\n            ]\n            nodes = self._docstore.get_nodes(node_ids)\n            query_result.nodes = nodes\n        else:\n            # NOTE: vector store keeps text, returns nodes.\n            # Only need to recover image or index nodes from docstore\n            for i in range(len(query_result.nodes)):\n                source_node = query_result.nodes[i].source_node\n                if (not self._vector_store.stores_text) or (\n                    source_node is not None and source_node.node_type != ObjectType.TEXT\n                ):\n                    node_id = query_result.nodes[i].node_id","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/indices/multi_modal/retriever.py#L218-L254","documentation":"When a vector store query result comes back without nodes, the multimodal retriever tries to recover nodes from the docstore by id — and if ids are also None there is nothing to resolve, so it raises ValueError. Custom or partial vector store implementations that populate neither query_result.nodes nor query_result.ids hit this; well-behaved stores must return at least one of the two.","triggerScenarios":"Using a custom BasePydanticVectorStore subclass whose query() returns a VectorStoreQueryResult with nodes=None and ids=None; a store integration bug (e.g. returning only similarities/embeddings); querying a store whose results were built incompletely.","commonSituations":"Writing your own vector store adapter for a niche database and forgetting to map ids back; upgrading a store integration where the result-mapping code changed; multimodal retrieval against stores validated only on the single-modal path.","solutions":["Fix the store's query() to populate at least ids (node ids matching what was stored) or full nodes in VectorStoreQueryResult.","If using a third-party integration, upgrade it — and verify with a one-off query that the result carries nodes or ids.","Pre-check the result contract in tests: run vector_store.query(...) once and assert result.nodes is not None or result.ids is not None."],"exampleFix":"# before\ndef query(self, query, **kwargs):\n    return VectorStoreQueryResult(similarities=sims)  # no nodes/ids -> ValueError\n\n# after\ndef query(self, query, **kwargs):\n    return VectorStoreQueryResult(nodes=retrieved_nodes, ids=retrieved_ids, similarities=sims)","handlingStrategy":"validation","validationCode":"# smoke-test the store contract once at startup\nq = vector_store.query(__import__('llama_index.core.vector_stores', fromlist=['VectorStoreQuery']).VectorStoreQuery(query_str=\"__probe__\", similarity_top_k=1))\nassert q.nodes is not None or q.ids is not None, \"store must return nodes or ids\"","typeGuard":"from llama_index.core.vector_stores.types import VectorStoreQueryResult\n\ndef result_resolvable(r: VectorStoreQueryResult) -> bool:\n    return r.nodes is not None or r.ids is not None","tryCatchPattern":"try:\n    nodes_with_scores = retriever.retrieve(q)\nexcept ValueError as e:\n    if \"at least one of nodes or ids\" in str(e):\n        # custom store bug: fix query() to return ids/nodes; surface clearly\n        raise RuntimeError(\"vector store query() must populate nodes or ids\") from e\n    raise","preventionTips":["When writing a custom vector store, always populate ids (minimum) in query results.","Add a contract test for custom stores: assert nodes or ids present after a round-trip query+ingest.","Run multimodal retrieval against your store in CI, not just single-modal."],"tags":["llama-index","multimodal","retriever","vector-store","custom-integration"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}