n8n-io/n8n · error · NodeOperationError

No audio data returned

Error message

No audio data returned

What it means

Thrown when the /t2a_v2 response has a successful status_code (0) but response.data.audio is missing or empty. This is a response-shape inconsistency: MiniMax signalled success yet did not return the synthesized audio payload the node expects.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/actions/audio/tts.operation.ts:242

	if (options.languageBoost) {
		body.language_boost = options.languageBoost;
	}

	const response = (await apiRequest.call(this, 'POST', '/t2a_v2', {
		body,
	})) as T2AResponse;

	if (response.base_resp?.status_code !== 0) {
		throw new NodeOperationError(
			this.getNode(),
			`Text-to-speech failed: ${response.base_resp?.status_msg || 'Unknown error'}`,
		);
	}

	const audioData = response.data?.audio;
	if (!audioData) {
		throw new NodeOperationError(this.getNode(), 'No audio data returned');
	}

	const jsonData: IDataObject = {
		audioLength: response.extra_info?.audio_length,
		audioFormat: response.extra_info?.audio_format,
		audioSize: response.extra_info?.audio_size,
		wordCount: response.extra_info?.word_count,
		usageCharacters: response.extra_info?.usage_characters,
	};

	if (downloadAudio) {
		const audioResponse = await this.helpers.httpRequest({
			method: 'GET',
			url: audioData,
			encoding: 'arraybuffer',
			returnFullResponse: true,
		});

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Retry the identical request — most occurrences are transient.
  2. Log the full response body to confirm whether data.audio is truly absent vs. moved.
  3. Verify the base URL in credentials points at the official MiniMax endpoint (https://api.minimax.io/v1) and not a filtering proxy.
  4. Shorten input text and retry to rule out a partial-failure edge case.
Defensive patterns

Strategy: retry

Validate before calling

// There is no caller-side input that prevents an upstream success-with-no-audio glitch.
// The only meaningful pre-check is to confirm the request shape matches the API contract.
function validateTtsRequestShape(body: IDataObject): string | null {
  if (typeof body.text !== 'string' || body.text.length === 0) return 'body.text must be a non-empty string';
  if (typeof body.voice_setting !== 'object' || body.voice_setting === null) return 'body.voice_setting is required';
  return null;
}

Type guard

function hasAudioPayload(r: unknown): r is { data: { audio: string } } {
  return typeof (r as { data?: { audio?: unknown } })?.data?.audio === 'string' &&
    ((r as { data: { audio: string } }).data.audio.length > 0);
}

Try / catch

async function ttsWithRetry(apiRequest: any, body: IDataObject, maxAttempts = 3): Promise<T2AResponse> {
  let lastErr: Error | null = null;
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const response = (await apiRequest.call(this, 'POST', '/t2a_v2', { body })) as T2AResponse;
    if (response.base_resp?.status_code !== 0) {
      throw new NodeOperationError(this.getNode(), `Text-to-speech failed: ${response.base_resp?.status_msg || 'Unknown error'}`);
    }
    if (response.data?.audio) return response; // success with payload
    lastErr = new Error('No audio data returned; retrying');
    await sleep(1000 * (attempt + 1));
  }
  throw new NodeOperationError(this.getNode(), lastErr?.message ?? 'No audio data returned');
}

Prevention

When it happens

Trigger: Transient MiniMax backend glitch returning success without audio; API version change that moved audio bytes to a different field; extremely long input where the service partially failed after marking success; response truncated by an intermediary proxy.

Common situations: Rare upstream bug; running against a non-standard base URL (custom proxy/gateway) that strips the data.audio field; stale credentials causing a degraded response; very long text near the limit.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/cedcf9bd04adff88. Report an issue: GitHub.