{"record":{"id":"4a0541748e1cc696","repo":"FoundationAgents/MetaGPT","slug":"missing-query-bundle-in-extra-info","errorCode":null,"errorMessage":"Missing query bundle in extra info.","messagePattern":"Missing query bundle in extra info\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/rag/rankers/object_ranker.py","lineNumber":35,"sourceCode":"    Assumes nodes is list of ObjectNode with score.\n    \"\"\"\n\n    field_name: str = Field(..., description=\"field name of the object, field's value must can be compared.\")\n    order: Literal[\"desc\", \"asc\"] = Field(default=\"desc\", description=\"the direction of order.\")\n    top_n: int = 5\n\n    @classmethod\n    def class_name(cls) -> str:\n        return \"ObjectSortPostprocessor\"\n\n    def _postprocess_nodes(\n        self,\n        nodes: list[NodeWithScore],\n        query_bundle: Optional[QueryBundle] = None,\n    ) -> list[NodeWithScore]:\n        \"\"\"Postprocess nodes.\"\"\"\n        if query_bundle is None:\n            raise ValueError(\"Missing query bundle in extra info.\")\n\n        if not nodes:\n            return []\n\n        self._check_metadata(nodes[0].node)\n\n        sort_key = lambda node: json.loads(node.node.metadata[\"obj_json\"])[self.field_name]\n        return self._get_sort_func()(self.top_n, nodes, key=sort_key)\n\n    def _check_metadata(self, node: ObjectNode):\n        try:\n            obj_dict = json.loads(node.metadata.get(\"obj_json\"))\n        except Exception as e:\n            raise ValueError(f\"Invalid object json in metadata: {node.metadata}, error: {e}\")\n\n        if self.field_name not in obj_dict:\n            raise ValueError(f\"Field '{self.field_name}' not found in object: {obj_dict}\")\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/rag/rankers/object_ranker.py#L17-L53","documentation":"ObjectSortPostprocessor._postprocess_nodes requires a QueryBundle because it sorts nodes independently of query similarity; llama-index calls postprocessors with query_bundle derived from the query string. If retrieval is invoked without a query (e.g. retrieval from an explicit node list, or a custom pipeline that passes query_bundle=None), this ValueError fires.","triggerScenarios":"Retriever.retrieve(...) called with no query argument so llama-index forwards query_bundle=None into the postprocessor; integrating ObjectSortPostprocessor into a query engine that was constructed without a query transformer that produces a QueryBundle.","commonSituations":"Using the object ranker in a custom llama-index pipeline or retriever that calls _postprocess_nodes directly; calling retriever.retrieve() with empty/None query during testing; embedding-only retrieval flows that skip query construction.","solutions":["Always call retriever.retrieve(\"your query text\") or query_engine.query(...) so a QueryBundle is built and passed through","If driving the postprocessor manually, construct QueryBundle(query_str) and pass it as query_bundle","Guard custom pipelines: skip or no-op the object ranker when no query string is available"],"exampleFix":"// before\nnodes = retriever.retrieve(None)  # ValueError inside ObjectSortPostprocessor\n\n// after\nfrom llama_index.core import QueryBundle\nnodes = retriever.retrieve(\"sort products by price\")","handlingStrategy":"validation","validationCode":"if not query_str:\n    raise ValueError(\"a non-empty query string is required when the object ranker is in the pipeline\")\nnodes = retriever.retrieve(query_str)","typeGuard":null,"tryCatchPattern":"try:\n    nodes = retriever.retrieve(query)\nexcept ValueError as e:\n    if \"Missing query bundle\" in str(e):\n        from llama_index.core import QueryBundle\n        nodes = ranker.postprocess_nodes(retriever.retrieve_nodes_for_query(QueryBundle(query)), query_bundle=Bundle(query))\n    raise","preventionTips":["Always pass a non-empty query string through retrieve/query so llama-index builds a QueryBundle","In custom pipelines, construct QueryBundle(query_str) explicitly before postprocessing","Skip query-independent postprocessors in flows that legitimately have no query"],"tags":["rag","reranker","llama-index","query"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}