decolua/9router · error · Error

MiniMax TTS returned no audio

Error message

MiniMax TTS returned no audio

What it means

MiniMax's non-streaming T2A API returns audio as a hex-encoded string. `hexToBase64` converts it to base64 and throws this error when the hex string is empty/absent (after trim). It fires when the upstream response contains no `audio_hex`/`data.audio` value at all.

Source

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

import { Buffer } from "node:buffer";

function hexToBase64(audioHex) {
  const clean = typeof audioHex === "string" ? audioHex.trim() : "";
  if (!clean) throw new Error("MiniMax TTS returned no audio");
  if (clean.length % 2 !== 0 || !/^[0-9a-f]+$/i.test(clean)) {
    throw new Error("MiniMax TTS returned invalid audio");
  }
  return Buffer.from(clean, "hex").toString("base64");
}

// MiniMax T2A HTTP: returns hex-encoded audio in non-streaming mode.
export default async function minimaxTts({ baseUrl, apiKey, text, modelId, voiceId }) {
  const res = await fetch(baseUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json", "Authorization": `Bearer ${apiKey}` },
    body: JSON.stringify({
      model: modelId || "speech-2.8-hd",
      text,
      stream: false,
      language_boost: "auto",
      output_format: "hex",
      voice_setting: {

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Log the full parsed response to see which field (if any) holds audio and whether an in-body error message exists
  2. Ensure `text` is non-empty and the model/voice IDs are valid for MiniMax T2A
  3. Confirm you are in non-streaming mode — hex audio is only returned there; handle streaming chunks separately
  4. Check `base_resp.status_code` even on 200; a nonzero code means the audio key is legitimately absent

Example fix

// before
const hex = data.data?.audio;
const b64 = hexToBase64(hex); // throws 'no audio' if undefined
// after
if (data.base_resp?.status_code !== 0) throw new Error(data.base_resp?.status_msg);
const b64 = hexToBase64(data.data?.audio);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!text?.trim()) throw new Error('text required for MiniMax TTS');
if (data.base_resp?.status_code !== 0) throw new Error(data.base_resp?.status_msg || 'MiniMax upstream error');

Type guard

const isHexAudio = (v) => typeof v === 'string' && v.trim().length > 0 && v.trim().length % 2 === 0 && /^[0-9a-f]+$/i.test(v.trim());

Try / catch

try { return await minimaxTts(...); } catch (e) { if (e.message === 'MiniMax TTS returned no audio') { logger.error('minimax empty audio', { status: data?.base_resp }); return fallbackTts(text); } throw e; }

Prevention

When it happens

Trigger: MiniMax responds 200 with `base_resp.status_code === 0` but no audio hex field — e.g. empty text input, voice/model mismatch, or a response shape where the audio key is absent.

Common situations: Empty or whitespace-only text passed through; wrong modelId/voiceId combo yielding silent success; MiniMax changing the response field name; streaming vs non-streaming mode confusion (stream mode returns chunks, not hex).

Related errors


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