{"record":{"id":"89283c05ab06e08c","repo":"MiniMax-AI/skills","slug":"video-generation-failed-json-dumps-data-indent","errorCode":null,"errorMessage":"Video generation failed: {json.dumps(data, indent=2)}","messagePattern":"Video generation failed: (.+?)","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/frontend-dev/scripts/minimax_video.py","lineNumber":101,"sourceCode":"            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},\n        timeout=30,\n    )\n    resp.raise_for_status()\n    data = resp.json()","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/frontend-dev/scripts/minimax_video.py#L83-L119","documentation":"poll_task() saw status=='Fail' — the backend reports the video generation did not succeed. The full JSON (which usually contains a fail reason/code) is dumped. This is a terminal state for the task; it will not transition to Success on its own.","triggerScenarios":"Content-policy rejection of the prompt; prompt exceeding 2000 chars or malformed camera-command brackets; an unsupported model/resolution/duration combination that the API accepted at create but rejected at generation; internal backend generation error; unsafe/toxic content detection.","commonSituations":"Prompt with disallowed content; camera commands like [Truck left]/[Push in] used with a model that doesn't support them; 1080P requested on a model/tier without it; overloaded backend marking tasks Fail; region/key mismatch causing generation-side rejection.","solutions":["Read the dumped JSON for the fail reason/code and address it directly (content, params, or model).","Simplify: lower resolution (768P/720P), reduce duration to 6, disable prompt_optimizer, remove camera brackets.","Rephrase the prompt to avoid policy-sensitive terms and retry as a NEW task (the failed task_id cannot be revived).","Confirm model/resolution/duration is a supported combo for your account/region."],"exampleFix":"// before: hard fail, lose the reason inside a SystemExit string\nelif status == \"Fail\":\n    raise SystemExit(f\"failed: {data}\")\n\n// after: surface the structured fail code for actionable handling\nelif status == \"Fail\":\n    reason = data.get(\"fail_info\", {}).get(\"reason\", \"unknown\")\n    if reason in (\"content_policy\", \"sensitive\"):\n        prompt = sanitize(prompt)\n    raise VideoGenFailed(task_id, reason, data)","handlingStrategy":"try-catch","validationCode":"def safe_prompt(prompt: str) -> str:\n    \"\"\"Trim length and strip content-policy-sensitive tokens before submit.\"\"\"\n    p = prompt[:2000]\n    for token in (\"[Truck left]\", \"[Push in]\"):\n        p = p.replace(token, \"\")  # drop camera cmds unsupported by the model\n    return p.strip() or \"a short clip\"","typeGuard":"def is_failed_status(data: dict) -> bool:\n    \"\"\"True when the video task reached a terminal Fail state.\"\"\"\n    return data.get(\"status\") == \"Fail\"","tryCatchPattern":"import subprocess, sys\ntry:\n    subprocess.run([sys.executable, \"minimax_video.py\", prompt, \"-o\", out, \"--resolution\", \"768P\"], check=True, capture_output=True, text=True)\nexcept subprocess.CalledProcessError as e:\n    msg = (e.stderr or \"\") + (e.stdout or \"\")\n    if \"Video generation failed\" in msg:\n        # create a NEW task with a sanitized prompt / lower params\n        subprocess.run([sys.executable, \"minimax_video.py\", safe_prompt(prompt), \"-o\", out, \"--resolution\", \"720P\"], check=True)\n    else:\n        raise","preventionTips":["Sanitize prompts (length <=2000, drop unsupported camera brackets) before create_task.","Start at 768P/720P and duration 6; only raise to 1080P/10s once a combo is known to work for the account.","On Fail, always create a new task (the failed task_id cannot be revived).","Capture the fail reason from the dumped JSON to drive the corrected retry."],"tags":["api","content-policy","minimax","video"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}