jeecgboot/JeecgBoot · error · RuntimeException
语音生成异常: {message}
Error message
语音生成异常: {message} What it means
A generic catch-all at the bottom of VoiceServiceImpl.textToSpeechWithUser(). It rethrows RuntimeExceptions unchanged (e.g. the TTS API failure in error 123) and wraps any other checked exception -- IOException/InterruptedException from the HTTP call or FileSystemException writing the wav -- into a RuntimeException carrying the cause message.
Source
Thrown at jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/voice/service/impl/VoiceServiceImpl.java:100
// 调用公共TTS API生成音频
ttsApiHelper.generateAudio(vo.getContent(), audioFile, voice, speed);
// 返回结果
String voiceUrl = bizPath + "/" + fileName;
VoiceResultVo result = new VoiceResultVo();
result.setVoiceUrl(voiceUrl);
result.setFileName(fileName);
// 存入Redis
saveToRedis(vo, fileName, voiceUrl, loginUser);
return result;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
log.error("语音生成异常", e);
throw new RuntimeException("语音生成异常: " + e.getMessage(), e);
}
}
//update-begin---author:wangshuai ---date:2026-04-15 for:【QQYUN-14568】语音生成改为异步,支持切换菜单后重新获取结果-----------
@Override
public String generateAsync(VoiceGenerateVo vo) {
String taskId = UUID.randomUUID().toString().replace("-", "");
String taskKey = VOICE_TASK_PREFIX + taskId;
JSONObject pending = new JSONObject();
pending.put("status", "pending");
redisUtil.set(taskKey, pending.toJSONString(), VOICE_TASK_TTL);
// 在异步线程执行前先获取登录用户,避免子线程中 Shiro 上下文丢失
LoginUser loginUser = null;
try {
loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
} catch (Exception e) {View on GitHub (pinned to 96fb33f5ec)
Solutions
- Inspect the cause via the logged '语音生成异常' stacktrace (e.getMessage() is in the thrown text).
- Verify TTS apiHost/apiKey/model config (the underlying error 123 will surface for HTTP failures).
- Confirm jeecg.path.upload + /voice is writable and the volume has space.
- Raise config.getTimeout() if the error is a client-side timeout.
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight the upload/voice directory before TTS
Path dir = Paths.get(jeecgBaseConfig.getPath().getUpload(), "voice");
Files.createDirectories(dir);
if (!Files.isWritable(dir)) { throw new IOException("voice 目录不可写: " + dir); } Try / catch
// The method already separates RuntimeException (rethrown) from checked (wrapped).
// Callers should catch RuntimeException and surface it to the user as a TTS failure.
try {
return voiceService.textToSpeech(vo);
} catch (RuntimeException e) {
log.error("语音生成失败", e);
return Result.error("语音生成失败,请稍后重试");
} Prevention
- Validate the TTS provider config (apiHost/apiKey/model) on startup with a tiny request.
- Ensure the upload/voice directory is writable and on a volume with free space.
- Set a sane config.getTimeout() so HttpClient.send doesn't hang the thread.
When it happens
Trigger: ttsApiHelper.generateAudio() raises a non-RuntimeException: HttpClient.send() hits a network/connect timeout (config.getTimeout()); the upload/voice output dir cannot be created or the wav written; the worker thread is interrupted during the blocking HTTP send.
Common situations: TTS provider unreachable from the server; upload path on a read-only/full volume; thread interrupted (async cancellation); connectTimeout (30s) exceeded.
Related errors
- edge-tts 执行失败,退出码: {exitCode}
- TTS API调用失败,状态码: {statusCode},{errorBody}
- Specified file not found
- The file name can not null
- 存储路径校验失败: {storePath}
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/6966108138173bd6.
Report an issue: GitHub.