calesthio/OpenMontage · error · ValueError
advanced_lip_sync requires face_choose or face_id
Error message
advanced_lip_sync requires face_choose or face_id
What it means
ValueError from _build_advanced_request when _normalize_face_choose returns an empty list: inputs contained neither face_choose nor face_id. After identify_face reports the faces it found, the advanced call must say which face(s) to animate; omitting the selection is rejected client-side.
Source
Thrown at tools/avatar/kling_lip_sync.py:370
if inputs.get("video_id"):
payload["video_id"] = str(inputs["video_id"])
if inputs.get("video_url"):
payload["video_url"] = str(inputs["video_url"])
if not payload:
raise ValueError("Kling identify_face requires video_id or video_url")
return {
"path": "/v1/videos/identify-face",
"payload": payload,
"operation": "identify_face",
}
def _build_advanced_request(self, inputs: dict[str, Any]) -> dict[str, Any]:
session_id = str(inputs.get("session_id") or "").strip()
if not session_id:
raise ValueError("advanced_lip_sync requires session_id")
face_choose = self._normalize_face_choose(inputs)
if not face_choose:
raise ValueError("advanced_lip_sync requires face_choose or face_id")
if len(face_choose) != 1:
raise ValueError("advanced_lip_sync currently supports exactly one face_choose item")
face_item = face_choose[0]
audio_source = self._copy_audio_input(inputs, face_item)
self._copy_timing_fields(inputs, face_item)
payload: dict[str, Any] = {
"session_id": session_id,
"face_choose": face_choose,
}
self._copy_common_task_fields(inputs, payload)
return {
"protocol": "classic",
"path": "/v1/videos/advanced-lip-sync",
"payload": payload,
"operation": "advanced_lip_sync",
"model": "kling-official-lip-sync",
"audio_source": audio_source,
}View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Read the faces from the identify_face result (or the faces artifact file) and pass one as face_id.
- Simplest form: face_id='1' for the first detected face.
- Full form: face_choose=[{'face_id': '1', ...timing fields...}].
Example fix
// before
result = tool.run({"operation": "advanced_lip_sync", "session_id": sid, "audio_path": "a.mp3"})
// after
result = tool.run({"operation": "advanced_lip_sync", "session_id": sid, "face_id": "1", "audio_path": "a.mp3"}) Defensive patterns
Strategy: validation
Validate before calling
assert inputs.get("face_choose") or inputs.get("face_id"), \
"advanced_lip_sync needs a face selection from the identify result" Prevention
- Read the identify result's face list and pass one detected face_id
- Default to face_id='1' when the caller has no selection logic
When it happens
Trigger: Calling advanced_lip_sync with session_id but no face_choose and no face_id; face_choose present but falsy (empty list, empty dict).
Common situations: Developer skips reading the identify result's face list; face selection delegated to an LLM step that returned nothing.
Related errors
- face_choose items must include face_id
- Kling identify_face requires video_id or video_url
- advanced_lip_sync requires session_id
- advanced_lip_sync currently supports exactly one face_choose
- face_choose must be a list of face choice objects
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/8678123aa362f785.
Report an issue: GitHub.