MiniMax-AI/skills · error · SystemExit

No download_url in response: {json.dumps(data, indent=2)}

Error message

No download_url in response: {json.dumps(data, indent=2)}

What it means

download_video() called GET {API_BASE}/files/retrieve with a file_id; HTTP 2xx and base_resp OK, but data.file.download_url is empty/missing. Without the URL the video cannot be fetched, and the full JSON is dumped.

Source

Thrown at skills/frontend-dev/scripts/minimax_video.py:124

    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},
        timeout=30,
    )
    resp.raise_for_status()
    data = resp.json()
    _check_resp(data)

    download_url = data.get("file", {}).get("download_url", "")
    if not download_url:
        raise SystemExit(f"No download_url in response: {json.dumps(data, indent=2)}")

    print(f"  Downloading from {download_url[:80]}...")
    video_resp = requests.get(download_url, timeout=300)
    video_resp.raise_for_status()

    os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
    with open(output_path, "wb") as f:
        f.write(video_resp.content)

    print(f"OK: {len(video_resp.content)} bytes -> {output_path}")


def generate(
    prompt: str,
    output_path: str,
    model: str = "MiniMax-Hailuo-2.3",
    duration: int = 6,
    resolution: str = "768P",

View on GitHub (pinned to 60aaae52bb)

Solutions

  1. Retry files/retrieve after a short delay — the download URL often appears shortly after Success.
  2. Inspect the dumped JSON to find the correct key (e.g. data.download_url, data.file.url).
  3. Re-poll the task to confirm the file_id is still valid and re-retrieve.
  4. If it persists, fetch manually via the dashboard using the file_id.

Example fix

// before: single expected nested key
download_url = data.get("file", {}).get("download_url", "")

// after: try alternates and retry once
for _ in range(3):
    download_url = (data.get("file", {}).get("download_url")
                    or data.get("download_url")
                    or data.get("file", {}).get("url", ""))
    if download_url:
        break
    time.sleep(5); data = retrieve(file_id)
if not download_url:
    raise RuntimeError("no download_url after retries")
Defensive patterns

Strategy: retry

Validate before calling

def read_download_url(data: dict):
    """Return download URL from plausible locations, else None."""
    for path in (("file", "download_url"), ("download_url",), ("file", "url")):
        v = data
        for k in path:
            v = v.get(k, {}) if isinstance(v, dict) else None
        if v:
            return v
    return None

Type guard

def has_download_url(data: dict) -> bool:
    """True when the files/retrieve response carries a downloadable URL."""
    return bool(read_download_url(data))

Try / catch

for attempt in range(3):
    data = retrieve(file_id)
    if data.get("base_resp", {}).get("status_code", 0) == 0:
        url = read_download_url(data)
        if url:
            return url
    time.sleep(5)
raise RuntimeError("no download_url after retries")

Prevention

When it happens

Trigger: The file is not yet ready for retrieval (file_id exists but the downloadable artifact isn't attached yet); the file_id expired or was already consumed; a schema that nests download_url differently; transient backend issue producing an empty URL.

Common situations: Calling files/retrieve immediately after Success where file_id is set but the asset isn't linkable yet; region/endpoint returning the URL under a sibling key; expired link after a long delay between poll and download.

Related errors


AI-assisted analysis of MiniMax-AI/skills@60aaae52bb (2026-08-13). Data as JSON: /api/errors/f1ab98ba789c9467. Report an issue: GitHub.