calesthio/OpenMontage · error · ValueError
advanced_lip_sync currently supports exactly one face_choose
Error message
advanced_lip_sync currently supports exactly one face_choose item
What it means
ValueError from _build_advanced_request when the normalized face_choose list has zero or more than one entries. The underlying Kling advanced-lip-sync binding in this client handles exactly one face per call; multi-face or empty selections are rejected before the request is sent.
Source
Thrown at tools/avatar/kling_lip_sync.py:372
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,
}
@staticmethodView on GitHub (pinned to 95e1c3d0ab)
Solutions
- Pick one face per call: pass a single-item face_choose or a bare face_id.
- To animate multiple faces, run one advanced_lip_sync call per face (with the same session_id) and merge outputs afterwards.
- Empty list means the selection step failed — re-read the identify result and choose a face.
Example fix
// before
result = tool.run({..., "face_choose": [{"face_id": "1"}, {"face_id": "2"}]})
// after
r1 = tool.run({..., "face_choose": [{"face_id": "1"}]})
r2 = tool.run({..., "face_choose": [{"face_id": "2"}]}) Defensive patterns
Strategy: validation
Validate before calling
face_choose = inputs.get("face_choose") or ([{"face_id": str(inputs["face_id"])}] if inputs.get("face_id") else [])
assert len(face_choose) == 1, "one face per advanced_lip_sync call" Type guard
def is_single_face_selection(face_choose: list) -> bool:
return len(face_choose) == 1 Prevention
- Loop one call per face instead of batching multiple faces into one request
- Treat an empty selection as a bug in the upstream selection step
When it happens
Trigger: Passing face_choose with 2+ items (multi-person video) to one advanced_lip_sync call; passing an empty list explicitly.
Common situations: Identify found several faces and the caller forwards all of them; attempting batch animation in a single request.
Related errors
- advanced_lip_sync requires face_choose or face_id
- face_choose must be a list of face choice objects
- face_choose items must include face_id
- Unsupported Kling lip-sync operation: {operation}
- Kling identify-face response missing data.session_id: {data}
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/8f9837ff3502b7c4.
Report an issue: GitHub.