{"record":{"id":"5a8f2f18fbbb47cc","repo":"calesthio/OpenMontage","slug":"selected-face-id-selected-id-r-was-not-returned","errorCode":null,"errorMessage":"Selected face_id {selected_id!r} was not returned by identify_face","messagePattern":"Selected face_id (.+?) was not returned by identify_face","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/avatar/kling_lip_sync.py","lineNumber":493,"sourceCode":"                width = value.get(\"width\") or value.get(\"w\")\n                height = value.get(\"height\") or value.get(\"h\")\n                if width is not None and height is not None:\n                    return max(float(width), 0.0) * max(float(height), 0.0)\n        width = face.get(\"width\") or face.get(\"w\")\n        height = face.get(\"height\") or face.get(\"h\")\n        if width is not None and height is not None:\n            return max(float(width), 0.0) * max(float(height), 0.0)\n        return 0.0\n\n    @staticmethod\n    def _selected_face_record(\n        faces: list[dict[str, Any]], face_choose: list[dict[str, Any]]\n    ) -> dict[str, Any]:\n        selected_id = str(face_choose[0].get(\"face_id\") or \"\")\n        for face in faces:\n            if str(face.get(\"face_id\") or face.get(\"id\") or \"\") == selected_id:\n                return face\n        raise ValueError(f\"Selected face_id {selected_id!r} was not returned by identify_face\")\n\n    def _apply_face_timing_defaults(\n        self, inputs: dict[str, Any], face: dict[str, Any]\n    ) -> None:\n        face_start = int(face.get(\"start_time\") or 0)\n        face_end = int(face.get(\"end_time\") or 0)\n        face_choose = self._normalize_face_choose(inputs)\n        face_item = face_choose[0] if face_choose else {}\n        if inputs.get(\"sound_start_time\") is None and face_item.get(\"sound_start_time\") is None:\n            inputs[\"sound_start_time\"] = 0\n        if inputs.get(\"sound_insert_time\") is None and face_item.get(\"sound_insert_time\") is None:\n            inputs[\"sound_insert_time\"] = face_start\n        if inputs.get(\"sound_end_time\") is not None or face_item.get(\"sound_end_time\") is not None:\n            return\n\n        candidates: list[int] = []\n        audio_duration = self._local_audio_duration_ms(inputs)\n        if audio_duration:","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/avatar/kling_lip_sync.py#L475-L511","documentation":"Raised by KlingLipSyncTool._selected_face_record when the face_id the user selected (via face_choose or top-level face_id) does not match any face returned by the identify_face call the tool just made. The advanced lip-sync payload needs the detected face's timing (start_time/end_time), so the id must exist in the fresh detection results.","triggerScenarios":"Calling advanced lip-sync with a face_id from an earlier run or from a different video; stale face ids after the source video was re-uploaded (media ids change per upload); case/format mismatch such as passing an int id where detection returned a string (str() comparison handles this, but a genuinely different value fails).","commonSituations":"Caching face ids between sessions, editing the video between identify and lip-sync steps, or hand-typing a face id. Also occurs when identify_face is skipped and an invented id like \"face_1\" is passed.","solutions":["Run kling_official_face_identify on the same video id first, and use a face_id from that exact response","Do not reuse face ids across runs or across different video uploads; re-identify after any re-upload","If you selected by face_id from a previous response, verify the video input is byte-identical to the one used for detection"],"exampleFix":"# before\ninputs = {\"video_id\": vid, \"face_choose\": [\"face_1\"]}  # stale id\n\n# after\nfaces = identify_face(video_id=vid)\ninputs = {\"video_id\": vid, \"face_choose\": [faces[\"faces\"][0][\"face_id\"]]}","handlingStrategy":"validation","validationCode":"faces = identify_face(video_id=vid)[\"faces\"]\nvalid_ids = {str(f.get(\"face_id\") or f.get(\"id\")) for f in faces}\nchosen = [str(c[\"face_id\"]) for c in normalize_face_choose(inputs)]\nif not set(chosen) <= valid_ids:\n    raise ValueError(f\"stale face ids {set(chosen) - valid_ids}; re-run identify_face\")","typeGuard":null,"tryCatchPattern":"try:\n    tool.run(inputs)\nexcept ValueError as e:\n    if \"was not returned by identify_face\" in str(e):\n        faces = identify_face(video_id=inputs[\"video_id\"])[\"faces\"]\n        inputs[\"face_choose\"] = [{\"face_id\": faces[0][\"face_id\"]}]\n        return tool.run(inputs)\n    raise","preventionTips":["Always identify faces on the same uploaded video id right before lip-sync","Never cache face ids across runs or videos","Treat any hand-written face id as suspect until validated against the detection response"],"tags":["kling","lip-sync","face-id","stale-state"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}