decolua/9router · error · Error

MiniMax TTS error (${res.status})

Error message

MiniMax TTS error (${res.status})

What it means

When the MiniMax T2A HTTP call returns a non-2xx status, the handler prefers the in-body `base_resp.status_msg`, then the raw response text, and finally falls back to this generic message containing the HTTP status. It means the upstream rejected the request (auth, quota, invalid params, etc.) and no usable error text was extracted.

Source

Thrown at open-sse/handlers/ttsProviders/minimax.js:49

        bitrate: 128000,
        format: "mp3",
        channel: 1,
      },
    }),
  });

  const rawText = await res.text();
  let data = {};
  if (rawText) {
    try { data = JSON.parse(rawText); } catch { data = {}; }
  }

  const baseResp = data.base_resp || data.baseResp || {};
  const statusCode = Number(baseResp.status_code ?? baseResp.statusCode ?? 0);
  const statusMessage = baseResp.status_msg || baseResp.statusMsg || data.message || "";

  if (!res.ok) {
    throw new Error(statusMessage || rawText || `MiniMax TTS error (${res.status})`);
  }
  if (statusCode !== 0) {
    throw new Error(statusMessage || "MiniMax TTS upstream error");
  }

  return {
    base64: hexToBase64(data.data?.audio),
    format: data.extra_info?.audio_format || data.extraInfo?.audioFormat || "mp3",
  };
}

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Read `res.status` from the message: 401 → fix the API key; 429 → backoff/quota; 400 → validate modelId/voiceId/text and the group_id query param
  2. Log `rawText` (the response body) to surface MiniMax's real error detail, since the generic fallback means the body was empty or unparseable
  3. Check `base_resp.status_code` in the body even alongside non-2xx statuses for MiniMax's own error codes
  4. Retry with exponential backoff for 5xx/429; do not retry 4xx client errors

Example fix

// before
throw new Error(statusMessage || rawText || `MiniMax TTS error (${res.status})`);
// after
throw new Error(statusMessage || rawText || `MiniMax TTS error (${res.status})`);
// plus: log rawText once at source so the generic fallback is never the only signal
console.error('[minimax-tts] raw body:', rawText);
Defensive patterns

Strategy: retry

Validate before calling

if (!apiKey) throw new Error('MiniMax API key missing');
if (!text?.trim()) throw new Error('text required');

Type guard

const isMiniMaxErrorBody = (d) => d != null && typeof d === 'object' && d.base_resp != null && typeof d.base_resp.status_code === 'number';

Try / catch

try { return await minimaxTts(...); } catch (e) { const m = e.message.match(/MiniMax TTS error \((\d+)\)/); const code = m && parseInt(m[1]); if (code === 429 || (code && code >= 500)) { await sleep(backoff); return retry(); } throw e; }

Prevention

When it happens

Trigger: MiniMax returns 401 (invalid/expired API key), 429 (rate limit), 400 (bad model/voice/text), or 5xx — and `base_resp.status_msg`, `statusMsg`, `data.message`, and the raw text are all empty so only the status-templated message remains.

Common situations: Expired or wrong-region MiniMax API key (401); exhausted free quota (429); group_id missing from the URL (400); MiniMax outage (5xx).

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/91452aae0a240e8e. Report an issue: GitHub.