{"record":{"id":"9423463f03fe8eb4","repo":"ATH-MaaS/Pixelle-Video","slug":"seedance-api-id-data","errorCode":null,"errorMessage":"Seedance API 未返回任务 ID: {data}","messagePattern":"Seedance API 未返回任务 ID: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/api_services/video_seedance.py","lineNumber":140,"sourceCode":"                payload[key] = kwargs[key]\n\n        logger.info(f\"SeedanceVideoClient: 提交任务 model={model}, duration={duration}s\")\n        resp = requests.post(\n            url,\n            headers=self._headers(),\n            json=payload,\n            timeout=self.timeout,\n            proxies=self._proxies(),\n        )\n        \n        if not resp.ok:\n            logger.error(f\"Seedance 提交失败: {resp.text}\")\n            resp.raise_for_status()\n            \n        data = resp.json()\n        task_id = data.get(\"id\")\n        if not task_id:\n            raise RuntimeError(f\"Seedance API 未返回任务 ID: {data}\")\n            \n        return task_id\n\n    def _poll_until_done(self, task_id: str, max_polls: int = 120, interval: int = 5) -> str:\n        # 同步更新查询接口路径\n        url = f\"{self.base_url}/contents/generations/tasks/{task_id}\"\n        \n        for i in range(max_polls):\n            resp = requests.get(url, headers=self._headers(), timeout=30, proxies=self._proxies())\n            resp.raise_for_status()\n            data = resp.json()\n            \n            status = data.get(\"status\")\n            if status == \"succeeded\":\n                # 根据实际返回体，URL 位于 content.video_url 或 video_url\n                video_url = data.get(\"content\", {}).get(\"video_url\") or data.get(\"video_url\")\n                if not video_url:\n                    raise RuntimeError(f\"Seedance 任务成功但未返回视频 URL: {data}\")","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/api_services/video_seedance.py#L122-L158","documentation":"_submit_task raises RuntimeError when the Seedance API returns a 2xx response whose JSON body lacks an 'id' field, so no task can be polled. The client treats a missing task ID as an unexpected/malformed API response.","triggerScenarios":"POST to the task-submission endpoint returns success HTTP status but body has no 'id' — e.g. wrong endpoint version, an error payload returned with 200, or auth/billing errors shaped differently than expected.","commonSituations":"Expired or quota-exhausted API key returning an error body with HTTP 200; API contract changed; pointing base_url at a proxy/mock that returns different JSON; region-specific endpoints returning a different envelope.","solutions":["Log the full response body (it is embedded in the exception message) and inspect the actual JSON structure","Verify ARK_API_KEY validity, quota and billing on the Volcano Engine console","Confirm base_url matches the current Seedance API endpoint/version","If the API nests the ID (e.g. data['result']['id']), adjust the client's data.get(\"id\") accordingly"],"exampleFix":"// before\ntask_id = data.get(\"id\")\n// after\ntask_id = data.get(\"id\") or (data.get(\"result\") or {}).get(\"id\") or data.get(\"task_id\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    video = client.generate_video(prompt=p, image_path=img, save_path=out)\nexcept RuntimeError as e:\n    if \"未返回任务 ID\" in str(e):\n        logging.error(f\"Seedance submit returned no task id: {e}\")  # inspect body, check key/quota\n    else:\n        raise","preventionTips":["Log full response bodies for all Seedance API calls","Verify API key/quota before submitting tasks","Pin/monitor the API version your base_url points to"],"tags":["api-response","seedance","http","contract-change"],"backgroundTag":"unexpected-api-response","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}