{"record":{"id":"b70333a0181067b9","repo":"FoundationAgents/MetaGPT","slug":"field-self-field-name-not-found-in-object-ob","errorCode":null,"errorMessage":"Field '{self.field_name}' not found in object: {obj_dict}","messagePattern":"Field '(.+?)' not found in object: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"metagpt/rag/rankers/object_ranker.py","lineNumber":52,"sourceCode":"        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\n    def _get_sort_func(self):\n        return heapq.nlargest if self.order == \"desc\" else heapq.nsmallest\n","sourceCodeStart":34,"sourceCodeEnd":56,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/rag/rankers/object_ranker.py#L34-L56","documentation":"After successfully parsing obj_json, ObjectSortPostprocessor checks that the configured field_name exists in the decoded object dict; if the sort field is absent it raises this ValueError showing the full object. The ranker sorts by metadata[field_name], so a missing field makes sorting impossible.","triggerScenarios":"Constructing ObjectSortPostprocessor(field_name=\"price\") but the indexed objects' obj_json contains no \"price\" key; renaming a field in the data model without re-indexing; heterogeneous objects in one index where only some carry the field.","commonSituations":"Field name typo between the ranker config and the ingested data; schema drift after re-generating objects; mixing object types in a single index.","solutions":["Align field_name with an existing key: inspect json.loads(nodes[0].metadata['obj_json']).keys() and use that key","Re-index objects that all contain the sort field, or filter heterogeneous nodes before the ranker","Add the field with a default value during ingestion if it is genuinely optional"],"exampleFix":"// before\nranker = ObjectSortPostprocessor(field_name=\"cost\", top_n=3)  # objects have \"price\"\n\n// after\nranker = ObjectSortPostprocessor(field_name=\"price\", top_n=3)","handlingStrategy":"validation","validationCode":"import json\nobj = json.loads(nodes[0].node.metadata[\"obj_json\"])\nif ranker.field_name not in obj:\n    raise ValueError(f\"sort field '{ranker.field_name}' not in object keys {sorted(obj)}\")","typeGuard":"import json\n\ndef objects_have_field(nodes, field_name: str) -> bool:\n    return all(field_name in json.loads(n.node.metadata.get(\"obj_json\", \"{}\")) for n in nodes)","tryCatchPattern":"try:\n    nodes = ranker.postprocess_nodes(nodes, query_bundle=qb)\nexcept ValueError as e:\n    if \"not found in object\" in str(e):\n        # inspect keys and rebuild ranker with an existing field\n        keys = sorted(json.loads(nodes[0].node.metadata[\"obj_json\"]).keys())\n        raise ValueError(f\"pick field_name from {keys}\") from e\n    raise","preventionTips":["Derive field_name from the data: json.loads(obj_json).keys() at config time","Keep one object schema per index, or filter heterogeneous nodes before ranking","Re-index after any rename of the sort field"],"tags":["rag","metadata","schema","sorting"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}