spring-projects/spring-ai · warning
No speech response returned for prompt: + prompt
Error message
No speech response returned for prompt: + prompt
What it means
Warning logged by OpenAiAudioSpeechModel.call() when the speech synthesis request produced zero audio bytes (audioBytes.length == 0). The model returns a TextToSpeechResponse containing one Speech with an empty byte array rather than throwing, so callers can silently end up with empty audio files.
Source
Thrown at models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java:148
SpeechCreateParams params = buildSpeechCreateParams(mergedOptions, inputText, false);
RequestOptions requestOptions = this.buildRequestOptions(mergedOptions);
HttpResponse httpResponse = this.openAiClient.audio().speech().create(params, requestOptions);
Headers headers = httpResponse.headers();
byte[] audioBytes;
try (InputStream inputStream = httpResponse.body()) {
audioBytes = inputStream.readAllBytes();
}
catch (IOException e) {
throw new RuntimeException("Failed to read audio speech response", e);
}
if (audioBytes.length == 0) {
if (logger.isWarnEnabled()) {
logger.warn("No speech response returned for prompt: " + prompt);
}
return new TextToSpeechResponse(List.of(new Speech(new byte[0])));
}
Speech speech = new Speech(audioBytes);
OpenAiAudioSpeechResponseMetadata metadata = OpenAiAudioSpeechResponseMetadata.from(headers);
return new TextToSpeechResponse(List.of(speech), metadata);
}
@Override
public Flux<TextToSpeechResponse> stream(TextToSpeechPrompt prompt) {
Assert.notNull(prompt, "Prompt must not be null");
// Lets openSpeechStream/emitNextChunk tell a deliberate cancellation
// apart from a genuine I/O failure.
AtomicBoolean cancelled = new AtomicBoolean(false);
View on GitHub (pinned to 98a7beda4f)
Solutions
- Verify OPENAI_API_KEY and billing/quota status for the audio endpoints.
- Validate speech options (voice, model, speed, response format) against current OpenAI supported values.
- Check the raw HTTP response via an interceptor; an error body may be collapsed into empty bytes.
- Treat zero-length Speech audio as a failure in application code and retry or alert.
Example fix
// before
byte[] audio = speechModel.call(new SpeechPrompt(text, opts)).getResult().getOutput();
Files.write(path, audio); // creates empty file
// after
if (audio == null || audio.length == 0) throw new IllegalStateException("OpenAI TTS returned no audio for prompt");
Files.write(path, audio); Defensive patterns
Strategy: try-catch
Validate before calling
// validate options before calling Assert.notNull(options.getVoice(), "voice is required"); Assert.hasText(prompt.getText(), "prompt text is required");
Type guard
static boolean hasAudio(SpeechPromptResult r) {
return r != null && r.getSpeeches() != null && r.getSpeeches().stream().anyMatch(s -> s.getAudio() != null && s.getAudio().length > 0);
} Try / catch
byte[] audio = speechModel.call(prompt).getResult().getOutput();
if (audio == null || audio.length == 0) throw new IllegalStateException("OpenAI TTS produced no audio"); Prevention
- Validate OPENAI_API_KEY and billing before audio workloads
- Check voice/model/speed values against current OpenAI docs
- Verify file size before writing/serving generated audio
When it happens
Trigger: The OpenAI /audio/speech endpoint returns an empty body (read fully into a zero-length byte[]); IOException during reading is separate and thrown as RuntimeException. Triggered when the API returns 2xx with no payload or the response stream is empty.
Common situations: Invalid OpenAI API key or billing issues returning unusual empty responses; unsupported/invalid voice or model option values; proxies/gateways stripping response bodies; OpenAI service incidents.
Related errors
- No speech response returned for request: + requestContext.re
- Failed to read audio speech response
- Failed to read resource:
- No choices returned for prompt: ${prompt}
- Conversion from JSON to %s failed
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/e8518c44d3a31b5b.
Report an issue: GitHub.