vercel/ai · error · NoSpeechGeneratedError

No speech audio generated.

Error message

No speech audio generated.

What it means

The provider completed the speech request but returned no audio (empty or missing audio data). generateSpeech throws NoSpeechGeneratedError, carrying the provider response(s), since a speech result without audio is considered a failed generation. This surfaces provider-side anomalies instead of returning an empty audio file.

Source

Thrown at packages/ai/src/generate-speech/generate-speech.ts:149

    abortSignal,
  });

  const result = await retry(() =>
    resolvedModel.doGenerate({
      text,
      voice,
      outputFormat,
      instructions,
      speed,
      language,
      abortSignal,
      headers: headersWithUserAgent,
      providerOptions,
    }),
  );

  if (!result.audio || result.audio.length === 0) {
    throw new NoSpeechGeneratedError({ responses: [result.response] });
  }

  logWarnings({
    warnings: result.warnings,
    provider: resolvedModel.provider,
    model: resolvedModel.modelId,
  });

  return new DefaultSpeechResult({
    audio: new DefaultGeneratedAudioFile({
      data: result.audio,
      mediaType:
        detectMediaType({
          data: result.audio,
          topLevelType: 'audio',
        }) ?? 'audio/mp3',
    }),
    warnings: result.warnings,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Inspect the `responses` property of NoSpeechGeneratedError for provider error details/warnings
  2. Try a different voice/model id compatible with the provider
  3. Check input text for content that the provider may block
  4. Retry with a different provider to rule out a transient provider issue
  5. Capture API responses (fixtures) to verify what the provider actually returns

Example fix

// before
const { audio } = await generateSpeech({ model, text });
// after
try {
  const { audio } = await generateSpeech({ model, text });
} catch (e) {
  if (NoSpeechGeneratedError.isInstance(e)) {
    console.error('provider responses:', e.responses);
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Type guard

function isNoSpeechGeneratedError(e: unknown): e is NoSpeechGeneratedError {
  return NoSpeechGeneratedError.isInstance(e);
}

Try / catch

try {
  return await generateSpeech({ model, text });
} catch (e) {
  if (NoSpeechGeneratedError.isInstance(e)) {
    console.error('speech failed:', e.responses);
    return fallbackTts(text);
  }
  throw e;
}

Prevention

When it happens

Trigger: Provider returns an empty audio payload; the response was filtered/blocked (e.g. content policy) so no audio was produced; a provider bug or quota state yields a 200 response with no audio bytes; the model id cannot actually synthesize the requested text.

Common situations: Content-moderation blocks on the input text; misconfigured voice/model combos that silently produce empty output; mock/test providers returning no audio; proxy layers stripping response bodies.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/052d92c54120f4d0. Report an issue: GitHub.