calesthio/OpenMontage · error · ValueError

advanced_lip_sync requires session_id

Error message

advanced_lip_sync requires session_id

What it means

ValueError from _build_advanced_request when inputs.session_id is missing or whitespace after strip. advanced_lip_sync is the second half of a two-step flow: it reuses the session created by identify_face. Calling it standalone without that handle is a protocol error, not a transient failure.

Source

Thrown at tools/avatar/kling_lip_sync.py:367

        if inputs.get("video_path") and not (inputs.get("video_url") or inputs.get("video_id")):
            raise ValueError("Kling identify_face requires video_url or video_id; local video paths cannot be silently uploaded.")
        payload: dict[str, Any] = {}
        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",

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Run identify_face first and pass its returned session_id into advanced_lip_sync.
  2. Or use the tool's combined/auto flow, which merges session_id automatically (see the dispatch code above line 241).
  3. Verify the key name is exactly 'session_id'.

Example fix

// before
result = tool.run({"operation": "advanced_lip_sync", "face_id": "1", "audio_path": "a.mp3"})

// after
identify = tool.run({"operation": "identify_face", "video_url": v})
session_id = identify.data["session_id"]
result = tool.run({"operation": "advanced_lip_sync", "session_id": session_id, "face_id": "1", "audio_path": "a.mp3"})
Defensive patterns

Strategy: validation

Validate before calling

identify = tool.run({"operation": "identify_face", "video_url": video_url})
session_id = identify.data.get("session_id")
assert session_id, "identify_face must run first to produce session_id"

Prevention

When it happens

Trigger: Calling operation='advanced_lip_sync' without first running operation='identify_face'; session_id key misspelled or None because the identify step's result was not threaded through.

Common situations: Developer assumes advanced_lip_sync is self-contained; orchestration code drops the session_id between steps; stale session_id from a previous run (different failure — Kling rejects it server-side).

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/d42992bbf6a70841. Report an issue: GitHub.