decolua/9router · error · Error

MiniMax TTS returned invalid audio

Error message

MiniMax TTS returned invalid audio

What it means

`hexToBase64` validates the MiniMax audio hex string before decoding: it must have even length and contain only hex characters `[0-9a-f]`. Otherwise it throws this error. It means audio data was present but malformed as hex.

Source

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

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: {
        voice_id: voiceId || "English_expressive_narrator",
        speed: 1,

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Inspect the actual audio value — if it looks base64, use it directly instead of hex-decoding
  2. Check for odd-length truncation (proxy/timeout cutting the response) and retry
  3. Verify the MiniMax API version/model docs for the current audio encoding field (`audio_hex` vs `audio`)
  4. Sanitize: strip whitespace/`0x` prefixes and validate the full string with /^[0-9a-f]+$/i before decoding

Example fix

// before
const b64 = Buffer.from(clean, 'hex').toString('base64');
// after (handle base64-encoded responses too)
const b64 = /^[0-9a-f]+$/i.test(clean) && clean.length % 2 === 0
  ? Buffer.from(clean, 'hex').toString('base64')
  : clean; // already base64
Defensive patterns

Strategy: type-guard

Validate before calling

const audio = data?.data?.audio;
if (audio && !/^[0-9a-f]+$/.test(audio.trim())) console.warn('MiniMax audio is not hex — check API version');

Type guard

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

Try / catch

try { return await minimaxTts(...); } catch (e) { if (e.message === 'MiniMax TTS returned invalid audio') { logger.warn('non-hex audio payload — treating as base64 or failing over'); return fallbackTts(text); } throw e; }

Prevention

When it happens

Trigger: The audio field contains a non-hex string — truncated hex (odd length), a URL/base64-encoded value instead of hex, error text placed in the audio field, or double-encoded data.

Common situations: A MiniMax API format change (audio now returned base64, not hex); response truncation by a proxy; passing an already-base64 payload into the hex path by wiring the wrong field; protocol migration between API versions.

Related errors


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