{"record":{"id":"6ec967acfb684b20","repo":"MiniMax-AI/skills","slug":"api-error-base-resp-get-status-code-base-6ec967","errorCode":null,"errorMessage":"API Error [{base_resp.get('status_code')}]: {base_resp.get('status_msg')}","messagePattern":"API Error \\[(.+?)\\]: (.+?)","errorType":"exception","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"skills/frontend-dev/scripts/minimax_music.py","lineNumber":79,"sourceCode":"    if lyrics_optimizer:\n        payload[\"lyrics_optimizer\"] = True\n\n    resp = requests.post(\n        f\"{API_BASE}/music_generation\",\n        headers={\n            \"Authorization\": f\"Bearer {API_KEY}\",\n            \"Content-Type\": \"application/json\",\n        },\n        json=payload,\n        timeout=timeout,\n    )\n    resp.raise_for_status()\n    data = resp.json()\n\n    # Check API-level error\n    base_resp = data.get(\"base_resp\", {})\n    if base_resp.get(\"status_code\", 0) != 0:\n        raise SystemExit(f\"API Error [{base_resp.get('status_code')}]: {base_resp.get('status_msg')}\")\n\n    status = data.get(\"data\", {}).get(\"status\")\n    if status != 2:\n        raise SystemExit(f\"Generation incomplete (status={status}): {json.dumps(data, indent=2)}\")\n\n    audio_data = data.get(\"data\", {}).get(\"audio\", \"\")\n    if not audio_data:\n        raise SystemExit(f\"No audio in response: {json.dumps(data, indent=2)}\")\n\n    extra = data.get(\"extra_info\", {})\n\n    if output_format == \"hex\":\n        audio_bytes = bytes.fromhex(audio_data)\n    else:\n        # URL mode — audio_data is a URL string\n        audio_bytes = None\n\n    return {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/frontend-dev/scripts/minimax_music.py#L61-L97","documentation":"The HTTP call to music_generation succeeded (resp.raise_for_status() passed, i.e. HTTP 2xx) but the response body carried an application-level error: data.base_resp.status_code is non-zero. MiniMax communicates business/logic errors through base_resp rather than HTTP status codes, and status_msg holds the human-readable cause.","triggerScenarios":"POST {API_BASE}/music_generation with an invalid/disabled model name (e.g. a model not enabled for the account), an unsupported audio_setting combination (sample_rate/bitrate/format), prompt or lyrics exceeding char limits (prompt 2000, lyrics 3500), content-policy rejection of the lyrics, rate limiting, or account quota exhaustion.","commonSituations":"Using the overseas endpoint (api.minimax.io) with a China-mainland key or vice versa; requesting a model the account tier doesn't have access to; pasting lyrics with disallowed content; hitting a free-tier concurrency/quotat ceiling; sending is_instrumental together with lyrics the API rejects.","solutions":["Read the printed status_code and status_msg first — they name the exact cause (e.g. 1004 auth, 1027 rate limit, 1039 content).","Cross-check the chosen MINIMAX_API_BASE region against the key's account region and switch to the matching host.","Validate payload values against current limits (model in [music-2.5+, music-2.5], sample_rate in {16000,24000,32000,44100}, bitrate in {32000,64000,128000,256000}, format in {mp3,wav,pcm}).","If it is a transient/rate-limit code, back off and retry; if content/policy, shorten or rephrase prompt/lyrics."],"exampleFix":"// before: only HTTP errors surface\nresp.raise_for_status()\ndata = resp.json()\n\n// after: also surface base_resp business errors with context\nbase_resp = data.get(\"base_resp\", {})\ncode = base_resp.get(\"status_code\", 0)\nif code != 0:\n    raise RuntimeError(f\"music_generation failed code={code}: {base_resp.get('status_msg')}\")","handlingStrategy":"try-catch","validationCode":"ALLOWED = {\n    \"model\": {\"music-2.5+\", \"music-2.5\"},\n    \"sample_rate\": {16000, 24000, 32000, 44100},\n    \"bitrate\": {32000, 64000, 128000, 256000},\n    \"fmt\": {\"mp3\", \"wav\", \"pcm\"},\n}\ndef validate_music_payload(model, sample_rate, bitrate, fmt, prompt, lyrics):\n    assert model in ALLOWED[\"model\"], f\"bad model {model}\"\n    assert sample_rate in ALLOWED[\"sample_rate\"]\n    assert bitrate in ALLOWED[\"bitrate\"]\n    assert fmt in ALLOWED[\"fmt\"]\n    assert len(prompt) <= 2000, \"prompt > 2000 chars\"\n    assert len(lyrics) <= 3500, \"lyrics > 3500 chars\"","typeGuard":"def is_api_error(data: dict) -> bool:\n    \"\"\"True when a MiniMax response carries a non-zero base_resp.status_code.\"\"\"\n    base = data.get(\"base_resp\", {}) if isinstance(data, dict) else {}\n    return isinstance(base, dict) and base.get(\"status_code\", 0) != 0","tryCatchPattern":"import subprocess, sys\ntry:\n    subprocess.run([sys.executable, \"minimax_music.py\", \"--prompt\", p, \"-o\", out], check=True, capture_output=True, text=True)\nexcept subprocess.CalledProcessError as e:\n    out = e.stdout or \"\" + e.stderr or \"\"\n    if \"API Error [\" in out:\n        code, msg = parse_api_error(out)  # extract [code]: msg\n        if code in TRANSIENT_CODES:\n            time.sleep(backoff); retry()\n        else:\n            raise RuntimeError(f\"music API {code}: {msg}\") from e\n    raise","preventionTips":["Pre-validate model/sample_rate/bitrate/format against the documented enums before sending.","Truncate/guard prompt (<=2000) and lyrics (<=3500) lengths in the caller.","Match the API_BASE region to the key region to avoid auth/policy base_resp errors.","Treat base_resp codes as data — classify retryable vs terminal instead of always aborting."],"tags":["api","network","validation","minimax","music"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}