{"record":{"id":"67d094e2c48067e0","repo":"calesthio/OpenMontage","slug":"jimeng-task-done-but-no-video-url-data","errorCode":null,"errorMessage":"Jimeng task done but no video_url: {data}","messagePattern":"Jimeng task done but no video_url: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"tools/video/jimeng_video.py","lineNumber":318,"sourceCode":"        body = json.dumps({\n            \"req_key\": _REQ_KEY_VIDEO,\n            \"task_id\": task_id,\n            \"req_json\": json.dumps({\"return_url\": True}),\n        }, ensure_ascii=False).encode(\"utf-8\")\n\n        deadline = time.time() + timeout_seconds\n        while time.time() < deadline:\n            time.sleep(poll_interval)\n            headers = self._sign(\"POST\", \"/\", query, {}, body, ak, sk)\n            url = f\"https://{_HOST}/?{urllib.parse.urlencode(sorted(query.items()))}\"\n            resp = requests.post(url, data=body, headers=headers, timeout=30)\n            data = self._json_or_raise(resp)\n            self._check_code(resp.status_code, data)\n            status = (data.get(\"data\") or {}).get(\"status\", \"\")\n            if status == \"done\":\n                video_url = (data.get(\"data\") or {}).get(\"video_url\")\n                if not video_url:\n                    raise RuntimeError(f\"Jimeng task done but no video_url: {data}\")\n                return video_url\n            if status in (\"not_found\", \"expired\"):\n                raise RuntimeError(f\"Jimeng task invalid: status={status}\")\n        raise TimeoutError(f\"Jimeng task {task_id} did not finish within {timeout_seconds}s\")\n\n    @staticmethod\n    def _sign(\n        method: str, path: str, query_params: dict,\n        headers: dict, body: bytes, ak: str, sk: str,\n    ) -> dict:\n        now = datetime.now(timezone.utc)\n        x_date = now.strftime(\"%Y%m%dT%H%M%SZ\")\n        short_date = x_date[:8]\n\n        body_hash = hashlib.sha256(body).hexdigest()\n        headers = dict(headers)\n        headers[\"Host\"] = _HOST\n        headers[\"X-Date\"] = x_date","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/video/jimeng_video.py#L300-L336","documentation":"Raised when the Jimeng poll (CVSync2AsyncGetResult) reports status='done' but data.video_url is absent. 'done' is treated as terminal success and the video URL is expected at data.video_url; a completion without a URL means the artifact was not published where expected (or lives under a different key), so the tool raises with the full response embedded rather than returning None.","triggerScenarios":"Poll returns status 'done' while data lacks video_url — expired/aged-out CDN artifact, schema drift moving the URL (e.g. to a list of outputs), or a partial success where transcoding finished but upload failed server-side.","commonSituations":"Polling too long after completion (Jimeng result URLs can expire); multi-output generations returning video_url list or a different field name; provider-side publication failures after render; API revision changing the result shape.","solutions":["Inspect the {data} in the error to locate the actual result field; if it moved, the tool's extraction needs updating.","Poll promptly — don't leave long gaps between submit and result retrieval, since artifacts can age out.","Resubmit the task; publication-after-render failures usually clear on a fresh run.","Check for an OpenMontage patch if Jimeng changed the video_url contract."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = jimeng_video(inputs)\nexcept RuntimeError as e:\n    if \"no video_url\" in str(e):\n        result = jimeng_video(inputs)  # one retry: publication-after-render race\n    else:\n        raise","preventionTips":["Collect results promptly after submit; don't let hours pass before polling completes.","Download the returned video_url immediately and cache it locally — Jimeng URLs can expire.","Report recurring result-shape drift with the embedded response payload."],"tags":["jimeng","volcengine","api-contract","polling","missing-result"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}