calesthio/OpenMontage · error · ValueError

Kling lip-sync response contained no videos

Error message

Kling lip-sync response contained no videos

What it means

Raised by KlingLipSyncTool._download_videos when the Kling task response's outputs list is empty (or falsy). The task reached the download stage but returned zero video entries — typically a failed or partially-failed generation that still reported completion, or an unexpected response shape.

Source

Thrown at tools/avatar/kling_lip_sync.py:658

            value=inputs.get("sound_file"),
            label="Lip-sync audio file",
        )
        if not sound_file:
            raise ValueError("advanced_lip_sync requires audio_id, sound_file, sound_file_url, sound_file_path, or audio_path")
        payload["sound_file"] = sound_file
        return {
            "type": "sound_file",
            "source": inputs.get("sound_file_url") or sound_path or "inline",
        }

    def _download_videos(
        self,
        client: KlingClient,
        outputs: list[dict[str, Any]],
        inputs: dict[str, Any],
    ) -> list[Path]:
        if not outputs:
            raise ValueError("Kling lip-sync response contained no videos")
        base_path = Path(inputs.get("output_path", "kling_lip_sync.mp4"))
        paths: list[Path] = []
        for index, item in enumerate(outputs):
            url = self._output_url(item)
            suffix = extension_from_url(url, ".mp4")
            output_path = numbered_output_path(output_path_with_suffix(base_path, suffix), index, suffix)
            client.download(url, output_path)
            paths.append(output_path)
        return paths

    @staticmethod
    def _output_url(item: dict[str, Any]) -> str:
        url = item.get("url") or item.get("video_url") or item.get("resource_url")
        if url:
            return str(url)
        resource = item.get("resource") or {}
        if isinstance(resource, dict) and resource.get("url"):
            return str(resource["url"])

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Retry the task once — transient upstream failures sometimes produce empty outputs
  2. Inspect the full task response (status, error message fields) before the tool's download step to see the real Kling-side status/error
  3. Check that the audio meets Kling constraints (>=2s crop, valid format) and the face selection was valid
  4. If it persists, capture the raw response and report as a tool/API issue
Defensive patterns

Strategy: retry

Validate before calling

resp = client.wait_for_task(task_id)
if not resp.get("outputs"):
    log.warning("empty outputs; task status=%s msg=%s", resp.get("status"), resp.get("msg"))

Try / catch

try:
    paths = tool._download_videos(client, outputs, inputs)
except ValueError as e:
    if "no videos" in str(e) and attempt < MAX_RETRIES:
        outputs = client.wait_for_task(task_id, force_refresh=True).get("outputs", [])
        continue  # retry once with fresh task state
    raise

Prevention

When it happens

Trigger: Polling a Kling advanced/full lip-sync task whose final status contains no outputs array entries; a callback-driven flow where the callback payload lacked video data; upstream API change renaming the outputs field so the tool sees [].

Common situations: Kling-side generation failure reported as success; content-policy or audio-length rejections that produce no video; intermittent API quirks; version drift in the Kling response schema.

Related errors


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