calesthio/OpenMontage · error · ValueError

Kling lip-sync response item contained no downloadable URL:

Error message

Kling lip-sync response item contained no downloadable URL: {item}

What it means

Raised by KlingLipSyncTool._output_url when a single output item contains no URL under any known key: url, video_url, resource_url, or resource.url. The item exists but has no downloadable location, so the tool cannot fetch the rendered video. The message embeds the offending item for diagnosis.

Source

Thrown at tools/avatar/kling_lip_sync.py:677

        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"])
        raise ValueError(f"Kling lip-sync response item contained no downloadable URL: {item}")

    @staticmethod
    def _copy_common_task_fields(inputs: dict[str, Any], payload: dict[str, Any]) -> None:
        callback_url = validate_callback_url(inputs.get("callback_url"))
        if callback_url:
            payload["callback_url"] = callback_url
        if inputs.get("external_task_id"):
            payload["external_task_id"] = inputs["external_task_id"]

    @staticmethod
    def _callback_result_data(inputs: dict[str, Any], task_id: str) -> dict[str, Any]:
        callback_url = inputs.get("callback_url")
        if not callback_url:
            return {}
        return {
            "callback_url": str(callback_url),
            "callback_requested": True,
            "polling_used": True,

View on GitHub (pinned to 95e1c3d0ab)

Solutions

  1. Log the embedded item dict — it usually reveals the actual field name or a pending/expired status
  2. Wait for the task to be fully complete (not merely 'succeeded' at task level) before downloading, then retry
  3. If a new field name appears (e.g. 'download_url'), map it into item['url'] in your wrapper before the tool reads it, or patch _output_url and report upstream
Defensive patterns

Strategy: try-catch

Validate before calling

def item_has_url(item) -> bool:
    if item.get("url") or item.get("video_url") or item.get("resource_url"):
        return True
    r = item.get("resource")
    return isinstance(r, dict) and bool(r.get("url"))

bad = [i for i in outputs if not item_has_url(i)]
if bad:
    log.warning("output items without URLs: %s", bad)

Type guard

def item_has_url(item) -> bool:
    if item.get("url") or item.get("video_url") or item.get("resource_url"):
        return True
    r = item.get("resource")
    return isinstance(r, dict) and bool(r.get("url"))

Try / catch

try:
    url = extract_output_url(item)
except ValueError:
    log.warning("no URL in item; waiting and re-polling task: %s", item)
    outputs = client.wait_for_task(task_id, force_refresh=True).get("outputs", [])
    # re-attempt extraction once

Prevention

When it happens

Trigger: An outputs entry that only carries metadata (id, status, thumbnails) because the video asset is still processing or was purged; an upstream schema change introducing a new URL field name the tool does not know; an item whose resource is not a dict.

Common situations: Downloading too early after task completion; expired CDN links from a delayed download; Kling API version drift.

Related errors


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