MiniMax-AI/skills · error · SystemExit

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

Error message

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

What it means

After create_task() gets HTTP 200 and base_resp OK, it expects a task_id in the JSON. If absent, the response shape is unexpected — an API revision change, a proxy/gateway wrapper, or an error returned without a base_resp block. The full JSON is dumped to aid diagnosis.

Source

Thrown at skills/gif-sticker-maker/scripts/minimax_video.py:110

        "prompt_optimizer": prompt_optimizer,
    }

    if first_frame_image:
        payload["first_frame_image"] = first_frame_image

    resp = requests.post(
        f"{API_BASE}/video_generation",
        headers=_headers(),
        json=payload,
        timeout=30,
    )
    resp.raise_for_status()
    data = resp.json()
    _check_resp(data)

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


def poll_task(task_id: str, interval: int = 10, max_wait: int = 600) -> str:
    """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", "")

View on GitHub (pinned to 60aaae52bb)

Solutions

  1. Inspect the dumped JSON keys — they reveal whether the endpoint/contract changed.
  2. Confirm API_BASE ends in /v1 and points to the correct region for the key.
  3. Retry once; transient gateway wrappers sometimes intercept individual calls.

Example fix

# before
task_id = create_task(prompt=p, model=m)

# after - guard the contract before trusting the value
data = resp.json()
task_id = data.get('task_id')
if not task_id:
    # log full body, fall back to alternate key if API changed
    task_id = data.get('id') or data.get('task', {}).get('id')
    if not task_id:
        raise RuntimeError(f'unexpected response: {data}')
Defensive patterns

Strategy: try-catch

Validate before calling

def has_task_id(resp_json: dict) -> bool:
    return bool(resp_json.get('task_id'))
# after the POST, before relying on it:
if not has_task_id(data):
    raise RuntimeError(f'no task_id: {data}')

Type guard

def is_task_response(d) -> bool:
    return isinstance(d, dict) and isinstance(d.get('task_id'), str) and bool(d['task_id'])

Try / catch

try:
    task_id = create_task(prompt=p, model=m)
except SystemExit as e:
    raise RuntimeError(f'create_task returned no task_id: {e}') from e

Prevention

When it happens

Trigger: POST video_generation returns 200 with valid base_resp but no task_id key — e.g. API_BASE points to the wrong version path, a proxy wraps/renames the response, or a new API revision changed the contract.

Common situations: API_BASE missing the /v1 suffix or pointing to the wrong region; corporate proxy rewrites the body; SDK called against a newer/older API version than the script targets.

Related errors


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