MiniMax-AI/skills · error · SystemExit
Task succeeded but no file_id returned
Error message
Task succeeded but no file_id returned
What it means
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.
Source
Thrown at skills/frontend-dev/scripts/minimax_video.py:97
"""Poll task status until Success. Returns file_id."""
elapsed = 0
while elapsed < max_wait:
resp = requests.get(
f"{API_BASE}/query/video_generation",
headers=_headers(),
params={"task_id": task_id},
timeout=30,
)
resp.raise_for_status()
data = resp.json()
_check_resp(data)
status = data.get("status", "")
file_id = data.get("file_id", "")
if status == "Success":
if not file_id:
raise SystemExit("Task succeeded but no file_id returned")
print(f" Done! file_id={file_id}")
return file_id
elif status == "Fail":
raise SystemExit(f"Video generation failed: {json.dumps(data, indent=2)}")
else:
print(f" [{elapsed}s] Status: {status}...")
time.sleep(interval)
elapsed += interval
raise SystemExit(f"Timeout after {max_wait}s. task_id={task_id}, check manually.")
def download_video(file_id: str, output_path: str):
"""Retrieve download URL via file_id and save the video."""
resp = requests.get(
f"{API_BASE}/files/retrieve",
headers=_headers(),
params={"file_id": file_id},View on GitHub (pinned to 60aaae52bb)
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.
Example fix
// before: give up immediately on empty file_id
if status == "Success":
if not file_id:
raise SystemExit("no file_id")
// after: re-poll a few times after Success for file_id to settle
if status == "Success":
for _ in range(3):
if file_id:
return file_id
time.sleep(interval); data = query(task_id)
file_id = data.get("file_id", "")
raise RuntimeError("Success but file_id never appeared") Defensive patterns
Strategy: retry
Validate before calling
def poll_for_file_id(task_id, interval=10, settle_polls=3):
"""Poll until Success, then re-poll a few times waiting for file_id to appear."""
while True:
data = query(task_id)
status = data.get("status", "")
if status == "Success":
for _ in range(settle_polls):
fid = data.get("file_id", "")
if fid:
return fid
time.sleep(interval); data = query(task_id)
raise RuntimeError("Success but file_id never appeared")
elif status == "Fail":
raise RuntimeError(f"task failed: {data}")
time.sleep(interval) Type guard
def has_file_id(data: dict) -> bool:
"""True when a Success response carries a non-empty file_id."""
return data.get("status") == "Success" and bool(data.get("file_id", "")) Try / catch
if status == "Success":
for _ in range(3):
if file_id:
return file_id
time.sleep(interval); data = query(task_id); file_id = data.get("file_id", "")
raise RuntimeError("Success but no file_id after settle polls") Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Transient race where status flips to Success slightly before file_id is populated; schema drift; account/region returning file_id under a nested field.
Related errors
- No download_url in response: {json.dumps(data, indent=2)}
- No task_id in response: {json.dumps(data, indent=2)}
- Timeout after {max_wait}s. task_id={task_id}, check manually
- Generation incomplete (status={status}): {json.dumps(data, i
- No audio in response: {json.dumps(data, indent=2)}
AI-assisted analysis of MiniMax-AI/skills@60aaae52bb (2026-08-13).
Data as JSON: /api/errors/28db4f62fb13e6bd.
Report an issue: GitHub.