chinabugotech/hutool · error · AIException

TTS请求失败:

Error message

TTS请求失败: 

What it means

Thrown by HutoolServiceImpl.tts when the TTS endpoint response has Content-Type starting with application/json, which hutool-ai interprets as an error body rather than audio. The full JSON error body is appended to the message. Note this throw happens inside a try block whose outer catch (error 16) re-wraps it, so the user-visible message is actually 'TTS处理失败: TTS请求失败: <body>'.

Source

Thrown at hutool-ai/src/main/java/cn/hutool/ai/model/hutool/HutoolServiceImpl.java:124

	@Override
	public String embeddingVision(String text, String image) {
		String paramJson = buildEmbeddingVisionRequestBody(text, image);
		final HttpResponse response = sendPost(EMBEDDING_VISION, paramJson);
		return response.body();
	}

	@Override
	public InputStream tts(String input, final HutoolCommon.HutoolSpeech voice) {
		try {
			String paramJson = buildTTSRequestBody(input, voice.getVoice());
			final HttpResponse response = sendPost(TTS, paramJson);

			// 检查响应内容类型
			String contentType = response.header("Content-Type");
			if (contentType != null && contentType.startsWith("application/json")) {
				// 如果是JSON响应,说明有错误
				String errorBody = response.body();
				throw new AIException("TTS请求失败: " + errorBody);
			}
			// 默认返回音频流
			return response.bodyStream();
		} catch (Exception e) {
			throw new AIException("TTS处理失败: " + e.getMessage(), e);
		}
	}

	@Override
	public String stt(final File file) {
		final Map<String, Object> paramMap = buildSTTRequestBody(file);
		final HttpResponse response = sendFormData(STT, paramMap);
		return response.body();
	}


	@Override
	public String videoTasks(String text, String image, final List<HutoolCommon.HutoolVideo> videoParams) {

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Read the JSON body in the message to see the upstream error code/message.
  2. Verify the apiKey is valid and the TTS feature is enabled for the account.
  3. Use a supported HutoolCommon.HutoolSpeech voice value.
  4. Keep input text within the provider's length limits.
  5. Expect the outer wrapper: the real cause text follows 'TTS处理失败: TTS请求失败: '.

Example fix

// before
InputStream audio = service.tts("hello", HutoolCommon.HutoolSpeech.ALLOY);
// upstream rejects -> TTS请求失败: {"error":"invalid voice"}
// (then wrapped by error 16)

// after -- inspect the JSON body and use a supported voice
try {
    return service.tts(text, HutoolCommon.HutoolVoice.DEFAULT);
} catch (AIException e) {
    String body = e.getMessage().replaceFirst(".*TTS请求失败: ", "");
    log.error("tts upstream error body: {}", body);
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate inputs that typically yield a JSON error body
if (StrUtil.isBlank(input)) throw new IllegalArgumentException("empty tts input");
if (voice == null) throw new IllegalArgumentException("voice null");
if (StrUtil.isBlank(config.getApiKey())) throw new IllegalStateException("key missing");

Type guard

static boolean isSupportedVoice(HutoolCommon.HutoolSpeech v) {
    return v != null && java.util.EnumSet.of(
        /* list supported voices */ HutoolCommon.HutoolSpeech.ALLOY).contains(v);
}

Try / catch

// This inner throw is normally re-wrapped by error 16; see error 16's pattern.
// If observed directly, the JSON body follows "TTS请求失败: ".
String body = e.getMessage().substring(e.getMessage().indexOf(':') + 1).trim();
JSONObject err = JSONUtil.parseObj(body);

Prevention

When it happens

Trigger: Calling HutoolServiceImpl.tts(input, voice) when the upstream TTS service responds with JSON -- e.g. invalid/expired apiKey, quota exceeded, unsupported voice enum value, prompt too long, or the model/TTS feature not enabled for the account.

Common situations: Wrong or expired hutool AI key; the chosen HutoolSpeech voice is not supported by the account/plan; empty or over-long input text; upstream service degradation returning a JSON error.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/0fa44026a7ee5ebb. Report an issue: GitHub.