calesthio/OpenMontage · error · ValueError

Unsupported Kling lip-sync operation: {operation}

Error message

Unsupported Kling lip-sync operation: {operation}

What it means

ValueError from the Kling lip-sync tool dispatcher when the operation input matches neither 'identify_face', 'advanced_lip_sync', nor the auto/combined paths. The operation routes to completely different API endpoints (/v1/videos/identify-face vs /v1/videos/advanced-lip-sync), so an unknown value cannot be guessed. The error is caught by the tool's own except clause and returned as a failed ToolResult, not raised to the caller.

Source

Thrown at tools/avatar/kling_lip_sync.py:241

                        artifacts=[str(artifact_path)],
                        error="Multiple faces detected. Pass face_id/face_choose or set auto_select_face=True.",
                        cost_usd=self.estimate_cost({"operation": "identify_face"}),
                        duration_seconds=round(time.time() - start, 2),
                        model="kling-official-lip-sync",
                    )
                merged = {**inputs, "session_id": identify["session_id"], "face_choose": face_choose}
                selected_face = self._selected_face_record(identify["faces"], face_choose)
                self._apply_face_timing_defaults(merged, selected_face)
                request = self._build_advanced_request(merged)
                result = self._run_advanced_lip_sync(client, merged, request, start)
                result.data["faces_artifact_path"] = str(artifact_path)
                result.data["face_selection"] = selection
                result.artifacts.append(str(artifact_path))
                return result
            if operation == "advanced_lip_sync":
                request = self._build_advanced_request(inputs)
                return self._run_advanced_lip_sync(client, inputs, request, start)
            raise ValueError(f"Unsupported Kling lip-sync operation: {operation}")
        except (KlingAPIError, TimeoutError, ValueError, KeyError, FileNotFoundError) as exc:
            data: dict[str, Any] = {"provider": self.provider}
            if isinstance(exc, KlingAPIError):
                data.update(
                    {
                        "error_code": exc.code,
                        "request_id": exc.request_id,
                        "http_status": exc.http_status,
                        "account_usage_diagnostic": account_usage_hint_for_error(exc),
                    }
                )
            return ToolResult(success=False, data=data, error=f"Kling official lip-sync failed: {exc}")
        except Exception as exc:
            return ToolResult(success=False, data={"provider": self.provider}, error=f"Kling official lip-sync failed: {exc}")

    def _identify_faces(self, client: KlingClient, inputs: dict[str, Any]) -> dict[str, Any]:
        request = self._build_identify_request(inputs)
        data = client.post(request["path"], request["payload"])

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Set operation to one of the supported values: 'identify_face' or 'advanced_lip_sync' (check the dispatch block above line 241 for the full set including auto flows).
  2. Use underscores, not hyphens: 'identify_face', not 'identify-face'.
  3. Check ToolResult.success and ToolResult.error rather than expecting an exception — this failure returns a result object.

Example fix

// before
result = tool.run({"operation": "lip-sync", "video_url": v, "audio_path": a})

// after
result = tool.run({"operation": "advanced_lip_sync", "video_url": v, "audio_path": a})
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_OPS = {"identify_face", "advanced_lip_sync"}  # plus auto flows per dispatch
operation = str(inputs.get("operation") or "").strip()
assert operation in SUPPORTED_OPS, f"unsupported operation: {operation}"

Type guard

def is_supported_operation(op: str) -> bool:
    return op in {"identify_face", "advanced_lip_sync"}

Try / catch

result = tool.run(inputs)
if not result.success and "Unsupported Kling lip-sync operation" in (result.error or ""):
    # fix the operation name and re-run; this is a result, not an exception

Prevention

When it happens

Trigger: Passing operation='lip_sync', 'basic', 'sync', or any typo like 'identify-face' (hyphen instead of underscore) to kling_lip_sync.

Common situations: Operation names copied from Kling's raw API docs (hyphenated) instead of this tool's snake_case convention; version upgrade renaming operations; LLM agents guessing operation names.

Related errors


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