{"record":{"id":"34b5dc4901e7495e","repo":"ATH-MaaS/Pixelle-Video","slug":"video-url-code-rsp-code-message","errorCode":null,"errorMessage":"万象视频任务完成后仍未返回 video_url: code={rsp.code}, message={rsp.message}, task_id={task_id}, task_status={task_status}, output={self._safe_output_repr(rsp)}","messagePattern":"万象视频任务完成后仍未返回 video_url: code=(.+?), message=(.+?), task_id=(.+?), task_status=(.+?), output=(.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/api_services/video_dashscope.py","lineNumber":391,"sourceCode":"                )\n\n            logger.info(f\"DashscopeVideoClient: 任务已提交 task_id={task_id}, status={task_status}; 等待生成完成...\")\n            rsp = self._with_network_retry(\n                f\"wait task {task_id}\",\n                lambda: VideoSynthesis.wait(task=rsp, api_key=self.api_key),\n                max_attempts=8,\n                base_delay=5.0,\n            )\n            if rsp.status_code != HTTPStatus.OK:\n                raise RuntimeError(\n                    f\"万象视频任务查询失败: status={rsp.status_code}, \"\n                    f\"code={rsp.code}, message={rsp.message}, task_id={task_id}\"\n                )\n\n            video_url = self._extract_video_url(rsp)\n            task_status = self._extract_task_status(rsp)\n            if not video_url:\n                raise RuntimeError(\n                    \"万象视频任务完成后仍未返回 video_url: \"\n                    f\"code={rsp.code}, message={rsp.message}, task_id={task_id}, task_status={task_status}, \"\n                    f\"output={self._safe_output_repr(rsp)}\"\n                )\n\n        logger.info(f\"DashscopeVideoClient: 视频生成成功: {video_url}\")\n\n        # 确保输出目录存在\n        os.makedirs(os.path.dirname(save_path), exist_ok=True)\n\n        # 下载视频\n        resp = self._with_network_retry(\n            \"download video\",\n            lambda: requests.get(\n                video_url,\n                stream=True,\n                timeout=120,\n                proxies={\"http\": self.local_proxy, \"https\": self.local_proxy} if self.local_proxy else None,","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/api_services/video_dashscope.py#L373-L409","documentation":"DashscopeVideoClient.generate_video polls the DashScope VideoSynthesis task until wait() returns, but the final response still contains no video URL in its output. The client raises RuntimeError instead of returning a None URL, because the task reported completion (or wait() succeeded) yet the output payload lacks the expected video field.","triggerScenarios":"Calling generate_video on wan2.x models where the asynchronous task finishes with task_status not 'succeeded' (e.g. FAILED/CANCELED/UNKNOWN) or succeeds with an output structure missing video_url, so _extract_video_url(rsp) returns falsy after the VideoSynthesis.wait poll (video_dashscope.py:388-395).","commonSituations":"Content-policy rejection of the prompt/image by DashScope, exhausted API quota so the task silently fails, DashScope SDK version drift changing the response output schema so _extract_video_url can no longer find the URL field, or the task ending in a non-success state the poller doesn't detect.","solutions":["Read task_status and output in the exception message; if status is FAILED/CANCELED, fix the underlying cause reported in rsp.message (often prompt policy violation or quota).","Verify the DashScope SDK version matches what dashscope VideoSynthesis.wait returns; upgrade or pin dashscope and check _extract_video_url against the actual response shape.","Log the full _safe_output_repr(rsp) payload and compare against the model's documented output schema; adjust _extract_video_url if DashScope renamed fields.","Retry generation with a different prompt or seed if the message indicates content moderation or transient internal failure."],"exampleFix":"# before\nvideo_url = self._extract_video_url(rsp)\ntask_status = self._extract_task_status(rsp)\nif not video_url:\n    raise RuntimeError(\"万象视频任务完成后仍未返回 video_url: ...\")\n# after\nvideo_url = self._extract_video_url(rsp)\ntask_status = self._extract_task_status(rsp)\nif not video_url and task_status in (\"FAILED\", \"CANCELED\"):\n    raise RuntimeError(\n        f\"万象视频任务失败: status={task_status}, message={rsp.message}, task_id={task_id}\"\n    )\nif not video_url:\n    raise RuntimeError(\"万象视频任务完成后仍未返回 video_url: ...\")","handlingStrategy":"try-catch","validationCode":"# 提交前无法预知结果，但可先校验 prompt/配额\nif not prompt or not prompt.strip():\n    raise ValueError(\"prompt 不能为空\")\nif len(prompt) > 2000:\n    raise ValueError(\"prompt 过长，可能触发内容策略\")","typeGuard":"def has_video_url(rsp) -> bool:\n    return bool(getattr(rsp, 'output', None) and rsp.output.get('video_url'))","tryCatchPattern":"try:\n    url = client.generate_video(...)\nexcept RuntimeError as e:\n    if \"video_url\" in str(e):\n        # 解析 task_status；FAILED/CANCELED 时读取 message 修复输入后重试\n        logger.error(f\"DashScope 任务未产出视频: {e}\")\n    else:\n        raise","preventionTips":["Pin the dashscope SDK version and verify _extract_video_url against real responses after upgrades","Keep prompts within content policy to avoid silent task failures","Monitor DashScope quota so tasks don't fail server-side","Persist task_id so a failed wait can be investigated via the console"],"tags":["dashscope","async-task","missing-video-url","api-response"],"backgroundTag":"task-completed-no-result-url","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}