{"record":{"id":"d5237d93631d5a71","repo":"calesthio/OpenMontage","slug":"kling-video-response-contained-no-videos","errorCode":null,"errorMessage":"Kling video response contained no videos","messagePattern":"Kling video response contained no videos","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tools/video/kling_official_video.py","lineNumber":602,"sourceCode":"\n        for item in inputs.get(\"video_list\") or []:\n            if not isinstance(item, dict):\n                raise ValueError(\"video_list items must be objects\")\n            add_video(item, \"video_list\")\n        if inputs.get(\"reference_video_url\"):\n            add_video({\"video_url\": inputs[\"reference_video_url\"]}, \"reference_video_url\")\n        for url in inputs.get(\"video_urls\") or []:\n            add_video({\"video_url\": url}, \"video_urls\")\n        return video_list, references_used\n\n    def _download_videos(\n        self,\n        client: KlingClient,\n        outputs: list[dict[str, Any]],\n        inputs: dict[str, Any],\n    ) -> list[Path]:\n        if not outputs:\n            raise ValueError(\"Kling video response contained no videos\")\n        base_path = Path(inputs.get(\"output_path\", \"kling_official_video.mp4\"))\n        paths: list[Path] = []\n        for index, item in enumerate(outputs):\n            url = self._output_url(item)\n            suffix = extension_from_url(url, \".mp4\")\n            output_path = numbered_output_path(output_path_with_suffix(base_path, suffix), index, suffix)\n            client.download(url, output_path)\n            paths.append(output_path)\n        return paths\n\n    @staticmethod\n    def _output_url(item: dict[str, Any]) -> str:\n        url = item.get(\"url\") or item.get(\"video_url\") or item.get(\"resource_url\")\n        if url:\n            return str(url)\n        resource = item.get(\"resource\") or {}\n        if isinstance(resource, dict) and resource.get(\"url\"):\n            return str(resource[\"url\"])","sourceCodeStart":584,"sourceCodeEnd":620,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/kling_official_video.py#L584-L620","documentation":"Raised in `_download_videos` when the `outputs` list passed to it is empty. The tool has a task response it believes completed, but zero downloadable video objects came back, so there is nothing to save to `output_path`. This guards the download loop from iterating over nothing and returning an empty paths list that downstream stages would misinterpret as success.","triggerScenarios":"The Kling API returns a task result whose video list field is empty or missing (e.g. `works: []`); a caller passes `outputs=[]` directly; the response-parsing step extracted no items from an otherwise 'succeeded' task.","commonSituations":"Provider API changes that rename the output field so the extractor finds nothing; querying a task that succeeded but whose assets expired (24-hour Kling URL lifetime) and were stripped from the response; partial provider outages returning malformed payloads with a success status.","solutions":["Inspect the raw task response (`task_id`, status, and the full JSON) to see which field holds the videos — the extractor may be looking at the wrong key after an API change","Re-submit the generation: if the remote URLs expired, the task must be regenerated since Kling does not re-issue expired artifacts","If calling `_download_videos` yourself, guard with `if not outputs:` and re-query the task before failing","Report as a provider/API-contract bug if the response genuinely has status=succeeded with no works"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"outputs = task_result.get(\"works\") or task_result.get(\"videos\") or []\nif not outputs:\n    # re-query once before giving up\n    task = client.query(task_id)\n    outputs = task.get(\"works\") or []\nif not outputs:\n    raise ValueError(f\"task {task_id} returned no downloadable videos\")","typeGuard":null,"tryCatchPattern":"try:\n    paths = tool._download_videos(client, outputs, inputs)\nexcept ValueError as e:\n    if \"contained no videos\" in str(e):\n        log.warning(\"empty outputs for task; re-querying once\")\n        task = client.query(task_id)\n        outputs = extract_outputs(task)\n        if not outputs:\n            raise\n        paths = tool._download_videos(client, outputs, inputs)\n    else:\n        raise","preventionTips":["Always check task status is succeeded AND the works list is non-empty before downloading","Treat empty-outputs-on-success as a provider contract violation and log the full task JSON","Remember Kling remote URLs expire (~24h); download promptly after completion"],"tags":["kling","video-generation","empty-response","download"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}