{"record":{"id":"c7c3f763d6a69f0e","repo":"MiniMax-AI/skills","slug":"task-succeeded-but-no-file-id-returned-c7c3f7","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/gif-sticker-maker/scripts/minimax_video.py","lineNumber":133,"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":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/gif-sticker-maker/scripts/minimax_video.py#L115-L151","documentation":"poll_task() observed status == 'Success' but file_id is empty. The server marked the task done yet omitted the result reference — an inconsistent state that should not occur normally, often a propagation race.","triggerScenarios":"GET query/video_generation returns status 'Success' with empty or missing file_id. Most likely a race where Success is posted before the file_id is indexed server-side.","commonSituations":"Polling immediately after a Success transition; high server load delaying file metadata; transient API inconsistency.","solutions":["Re-poll once or twice after a short delay — file_id often populates within seconds of Success.","Use the task_id to query the MiniMax console manually.","Report to MiniMax support if the state persists across many polls."],"exampleFix":"# before\nfile_id = poll_task(task_id)\n\n# after - tolerate a brief propagation lag\nfor attempt in range(3):\n    file_id = poll_task(task_id)\n    if file_id:\n        break\n    time.sleep(5)","handlingStrategy":"retry","validationCode":"# before accepting Success, confirm file_id is present\nstatus = data.get('status')\nfile_id = data.get('file_id')\nif status == 'Success' and not file_id:\n    # re-query after a short wait rather than aborting\n    time.sleep(5); continue","typeGuard":"def success_with_file(d) -> bool:\n    return d.get('status') == 'Success' and isinstance(d.get('file_id'), str) and bool(d['file_id'])","tryCatchPattern":"for _ in range(3):\n    try:\n        file_id = poll_task(task_id)\n        break\n    except SystemExit as e:\n        if 'no file_id' in str(e):\n            time.sleep(5); continue\n        raise","preventionTips":["Treat Success without file_id as transient; re-poll before aborting.","Persist task_id so you can resume polling/recovery later.","Add small jitter between polls to avoid thundering-herd on recovery."],"tags":["api","video-generation","response-shape","retry"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}