{"record":{"id":"28db4f62fb13e6bd","repo":"MiniMax-AI/skills","slug":"task-succeeded-but-no-file-id-returned","errorCode":null,"errorMessage":"Task succeeded but no file_id returned","messagePattern":"Task succeeded but no file_id returned","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/frontend-dev/scripts/minimax_video.py","lineNumber":97,"sourceCode":"    \"\"\"Poll task status until Success. Returns file_id.\"\"\"\n    elapsed = 0\n    while elapsed < max_wait:\n        resp = requests.get(\n            f\"{API_BASE}/query/video_generation\",\n            headers=_headers(),\n            params={\"task_id\": task_id},\n            timeout=30,\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        _check_resp(data)\n\n        status = data.get(\"status\", \"\")\n        file_id = data.get(\"file_id\", \"\")\n\n        if status == \"Success\":\n            if not file_id:\n                raise SystemExit(\"Task succeeded but no file_id returned\")\n            print(f\"  Done! file_id={file_id}\")\n            return file_id\n        elif status == \"Fail\":\n            raise SystemExit(f\"Video generation failed: {json.dumps(data, indent=2)}\")\n        else:\n            print(f\"  [{elapsed}s] Status: {status}...\")\n            time.sleep(interval)\n            elapsed += interval\n\n    raise SystemExit(f\"Timeout after {max_wait}s. task_id={task_id}, check manually.\")\n\n\ndef download_video(file_id: str, output_path: str):\n    \"\"\"Retrieve download URL via file_id and save the video.\"\"\"\n    resp = requests.get(\n        f\"{API_BASE}/files/retrieve\",\n        headers=_headers(),\n        params={\"file_id\": file_id},","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/frontend-dev/scripts/minimax_video.py#L79-L115","documentation":"poll_task() saw status=='Success' but file_id is empty. file_id is needed to call files/retrieve and get the download URL, so a success without it is unrecoverable from this client's perspective.","triggerScenarios":"A query/video_generation response reporting Success but omitting file_id — backend edge case where the job is marked done before the file reference is attached, or a schema that places the id under a different key.","commonSituations":"Transient race where status flips to Success slightly before file_id is populated; schema drift; account/region returning file_id under a nested field.","solutions":["Re-query the same task_id after a short delay — file_id often appears on the next poll once status is Success.","Inspect the full response (capture it) to find the correct field location.","If it persists, treat the task as needing manual retrieval via the dashboard/query endpoint with the task_id.","Add a small post-Success re-poll window (e.g. 2–3 extra polls) before giving up."],"exampleFix":"// before: give up immediately on empty file_id\nif status == \"Success\":\n    if not file_id:\n        raise SystemExit(\"no file_id\")\n\n// after: re-poll a few times after Success for file_id to settle\nif status == \"Success\":\n    for _ in range(3):\n        if file_id:\n            return file_id\n        time.sleep(interval); data = query(task_id)\n        file_id = data.get(\"file_id\", \"\")\n    raise RuntimeError(\"Success but file_id never appeared\")","handlingStrategy":"retry","validationCode":"def poll_for_file_id(task_id, interval=10, settle_polls=3):\n    \"\"\"Poll until Success, then re-poll a few times waiting for file_id to appear.\"\"\"\n    while True:\n        data = query(task_id)\n        status = data.get(\"status\", \"\")\n        if status == \"Success\":\n            for _ in range(settle_polls):\n                fid = data.get(\"file_id\", \"\")\n                if fid:\n                    return fid\n                time.sleep(interval); data = query(task_id)\n            raise RuntimeError(\"Success but file_id never appeared\")\n        elif status == \"Fail\":\n            raise RuntimeError(f\"task failed: {data}\")\n        time.sleep(interval)","typeGuard":"def has_file_id(data: dict) -> bool:\n    \"\"\"True when a Success response carries a non-empty file_id.\"\"\"\n    return data.get(\"status\") == \"Success\" and bool(data.get(\"file_id\", \"\"))","tryCatchPattern":"if status == \"Success\":\n    for _ in range(3):\n        if file_id:\n            return file_id\n        time.sleep(interval); data = query(task_id); file_id = data.get(\"file_id\", \"\")\n    raise RuntimeError(\"Success but no file_id after settle polls\")","preventionTips":["After status flips to Success, re-poll a few times for file_id before giving up — it lags status.","Persist task_id so you can resume polling instead of re-creating the task.","Log the full Success payload when file_id is missing to detect schema drift.","Treat empty-file_id-on-Success as transient, not terminal."],"tags":["api","data-integrity","transient","minimax","video"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}