calesthio/OpenMontage · error · ValueError
Kling identify_face requires video_url or video_id; local vi
Error message
Kling identify_face requires video_url or video_id; local video paths cannot be silently uploaded.
What it means
ValueError from _build_identify_request when video_path is supplied but neither video_url nor video_id is. This is a deliberate guard: identify-face requires a Kling-hosted video, and the tool refuses to silently upload a local file (which would spend quota and have side effects the caller did not ask for). The message tells the developer the upload must be explicit.
Source
Thrown at tools/avatar/kling_lip_sync.py:350
"output": str(paths[0]),
"output_path": str(paths[0]),
"video_paths": [str(path) for path in paths],
"format": "mp4",
"cost_estimate_confidence": "low",
"cost_estimate_basis": "Conservative estimate pending official account-usage reconciliation.",
**self._account_usage_result(inputs, client),
**self._callback_result_data(inputs, task_id),
**probed,
},
artifacts=[str(path) for path in paths],
cost_usd=self.estimate_cost(inputs),
duration_seconds=round(time.time() - start, 2),
model="kling-official-lip-sync",
)
def _build_identify_request(self, inputs: dict[str, Any]) -> dict[str, Any]:
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)View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Upload the local video first (Kling upload/video-creation endpoint or a tool that returns video_id/video_url), then pass video_id or video_url.
- Or host the file at a public URL and pass video_url.
- Do not pass video_path together with the expectation of implicit upload — it will always fail fast.
Example fix
// before
result = tool.run({"operation": "identify_face", "video_path": "clip.mp4"})
// after
video_id = kling_upload("clip.mp4") # explicit upload step
result = tool.run({"operation": "identify_face", "video_id": video_id}) Defensive patterns
Strategy: validation
Validate before calling
if inputs.get("video_path") and not (inputs.get("video_url") or inputs.get("video_id")):
inputs["video_id"] = upload_video(inputs["video_path"]) # explicit upload Prevention
- Upload local videos explicitly and pass video_id/video_url — never rely on video_path for identify_face
- Build the upload step into the pipeline so local files always have a Kling-side reference
When it happens
Trigger: Calling kling_lip_sync operation='identify_face' (or the auto flow) with only video_path pointing to a local file.
Common situations: Pipeline renders a local video then immediately tries lip-sync; developer assumes the tool auto-uploads like some other tools do.
Related errors
- Kling identify_face requires video_id or video_url
- face_choose items must be strings or objects
- Kling avatar requires image_url or image_path
- mode must be one of: {', '.join(AVATAR_MODES)}
- Kling avatar requires audio_id, sound_file, sound_file_url,
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/29e2954a7b04ff0e.
Report an issue: GitHub.