{"record":{"id":"52e73afbaed8ee78","repo":"calesthio/OpenMontage","slug":"kling-identify-face-response-face-list-is-not-a-li","errorCode":null,"errorMessage":"Kling identify-face response face list is not a list","messagePattern":"Kling identify-face response face list is not a list","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/avatar/kling_lip_sync.py","lineNumber":273,"sourceCode":"            return ToolResult(success=False, data={\"provider\": self.provider}, error=f\"Kling official lip-sync failed: {exc}\")\n\n    def _identify_faces(self, client: KlingClient, inputs: dict[str, Any]) -> dict[str, Any]:\n        request = self._build_identify_request(inputs)\n        data = client.post(request[\"path\"], request[\"payload\"])\n        payload = data.get(\"data\") or {}\n        session_id = payload.get(\"session_id\")\n        if not session_id:\n            raise ValueError(f\"Kling identify-face response missing data.session_id: {data}\")\n        faces = (\n            payload.get(\"face_data\")\n            or payload.get(\"faces\")\n            or payload.get(\"face_list\")\n            or payload.get(\"face_infos\")\n            or payload.get(\"faces_info\")\n            or []\n        )\n        if not isinstance(faces, list):\n            raise ValueError(\"Kling identify-face response face list is not a list\")\n        if not faces:\n            raise ValueError(\"Kling identify-face response contained no faces\")\n        return {\n            \"session_id\": str(session_id),\n            \"faces\": faces,\n            \"raw_response\": data,\n            \"request\": request,\n        }\n\n    def _identify_result(self, inputs: dict[str, Any], identify: dict[str, Any], start: float) -> ToolResult:\n        artifact_path = self._write_faces_artifact(inputs, identify)\n        return ToolResult(\n            success=True,\n            data={\n                \"provider\": self.provider,\n                \"model\": \"kling-official-lip-sync\",\n                \"operation\": \"identify_face\",\n                \"session_id\": identify[\"session_id\"],","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/avatar/kling_lip_sync.py#L255-L291","documentation":"ValueError from _identify_faces when the face data field it finds is not a JSON list. The code tolerates five key names (face_data, faces, face_list, face_infos, faces_info); whichever matched first held a dict, string, or null-adjacent value instead of an array. This is a response-shape problem, not a user-input problem — Kling returned face data in an object wrapper (e.g. {items: [...]}) this parser does not unwrap.","triggerScenarios":"Gateway returning faces wrapped as {'faces': {'items': [...]}} or a pagination object; a 'faces' key holding a count or status string that truthy-checks past the or-chain.","commonSituations":"Kling API version differences between the international and Chinese endpoints; aggregator proxies reshaping responses.","solutions":["Look at the raw_response saved in the identify result/artifact to see the actual shape of the face field.","Unwrap the wrapper in _identify_faces: if isinstance(faces, dict): faces = faces.get('items') or faces.get('list') or [].","Pin the tool to the gateway endpoint version it was written against."],"exampleFix":"// before\nfaces = payload.get(\"face_data\") or payload.get(\"faces\") or ... or []\nif not isinstance(faces, list):\n    raise ValueError(\"Kling identify-face response face list is not a list\")\n\n// after\nfaces = payload.get(\"face_data\") or payload.get(\"faces\") or ... or []\nif isinstance(faces, dict):\n    faces = faces.get(\"items\") or faces.get(\"list\") or []\nif not isinstance(faces, list):\n    raise ValueError(\"Kling identify-face response face list is not a list\")","handlingStrategy":"type-guard","validationCode":"faces = payload.get(\"face_data\") or payload.get(\"faces\") or payload.get(\"face_list\") \\\n    or payload.get(\"face_infos\") or payload.get(\"faces_info\") or []\nif isinstance(faces, dict):\n    faces = faces.get(\"items\") or faces.get(\"list\") or []","typeGuard":"def is_face_list(faces: object) -> bool:\n    return isinstance(faces, list) and all(isinstance(f, (dict, str)) for f in faces)","tryCatchPattern":"if not is_face_list(faces):\n    log.error(\"unexpected face payload shape: %r\", faces)\n    raise ValueError(\"Kling identify-face response face list is not a list\")","preventionTips":["Normalize dict-wrapped lists before the isinstance check","Pin the gateway API version in tests so schema drift is caught in CI, not production"],"tags":["kling","lip-sync","schema-mismatch","api-response"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}