SubtitleEdit/subtitleedit · error · InvalidOperationException
VibeVoice (CrispASR) synthesis failed ({(int)response.Status
Error message
VibeVoice (CrispASR) synthesis failed ({(int)response.StatusCode}): {errorBody}{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}{LaunchCmdSuffix} What it means
InvalidOperationException thrown when the VibeVoice /v1/audio/speech endpoint returns a non-success status. The response body is read via SafeReadErrorAsync and embedded along with the server log and launch command. Detailed context (voice, text, request JSON, response body) is logged via Se.LogError before the throw.
Source
Thrown at src/ui/Features/Video/TextToSpeech/Engines/VibeVoiceCrispAsr.cs:433
+ (string.IsNullOrEmpty(serverLog) ? string.Empty : $"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}")
+ LaunchCmdSuffix(launchCommand),
ex);
}
using (response)
{
if (!response.IsSuccessStatusCode)
{
var errorBody = await SafeReadErrorAsync(response, cancellationToken);
var serverLog = SnapshotServerLog();
var launchCommand = _serverLaunchCommand;
var errMsg = $"VibeVoice (CrispASR) server error {(int)response.StatusCode} {response.StatusCode} — "
+ $"Voice: {vibeVoice}, Text: {text}, RequestJson: {body}, "
+ $"ResponseBody: {errorBody}, ServerLog: {serverLog}"
+ LaunchCmdSuffix(launchCommand);
Se.LogError(errMsg);
Se.WriteToolsLog(errMsg);
throw new InvalidOperationException(
$"VibeVoice (CrispASR) synthesis failed ({(int)response.StatusCode}): {errorBody}"
+ (string.IsNullOrEmpty(serverLog) ? string.Empty : $"{Environment.NewLine}Server log:{Environment.NewLine}{serverLog}")
+ LaunchCmdSuffix(launchCommand));
}
await using var fileStream = File.Create(outputFileName);
await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken);
await contentStream.CopyToAsync(fileStream, cancellationToken);
}
return new TtsResult(outputFileName, text);
}
private static string FormatLaunchCommand(string exe, System.Collections.ObjectModel.Collection<string> args)
{
static string Quote(string s) =>
!string.IsNullOrEmpty(s) && s.IndexOfAny(new[] { ' ', '\t' }) >= 0
? "\"" + s.Replace("\"", "\\\"") + "\""View on GitHub (pinned to 17a9f07487)
Solutions
- Read the embedded errorBody — the server states the exact rejected field.
- Confirm `voice` is Path.GetFileNameWithoutExtension(FilePath) — never the full path and never with .wav/.gguf.
- Re-import the reference as a 24 kHz mono WAV if the server rejects the audio format.
- If cloning attestations are required by this build, ensure CrispAsrTtsProvenance.AddSpeechAttestations is invoked and the user accepted cloning in settings.
Example fix
// before — full path triggers the path-traversal guard (HTTP 400) payload["voice"] = vibeVoice.FilePath; // after — bare stem only payload["voice"] = Path.GetFileNameWithoutExtension(vibeVoice.FilePath);
Defensive patterns
Strategy: validation
Validate before calling
// Always send the bare stem and a clamped speed. payload["voice"] = Path.GetFileNameWithoutExtension(vibeVoice.FilePath); payload["speed"] = Math.Clamp(Se.Settings.Video.TextToSpeech.VibeVoiceCrispAsrSpeed, 0.25, 4.0); CrispAsrTtsProvenance.AddSpeechAttestations(payload);
Try / catch
try { response = await HttpClient.PostAsync(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("synthesis failed"))
{ Se.LogError(ex); throw; } Prevention
- Send only the extension-less stem as `voice`.
- Keep the reference WAV at 24 kHz mono.
- Ensure cloning attestations are attached when the build requires them.
When it happens
Trigger: HTTP 400 because `voice` contained a path separator/extension (server's path-traversal guard); HTTP 400 for an out-of-range `speed` (clamped client-side, but a fork may bypass); HTTP 500 when the reference WAV under --voice-dir is missing or the wrong format; HTTP 404 if the route was renamed in a newer crispasr build.
Common situations: Sending the full FilePath instead of the bare stem (the code already sends the stem, but a regression can revert it); reference WAV not 24 kHz mono; voice cloning attestations rejected by a build that gates cloning; route drift between crispasr versions.
Related errors
- Qwen3 TTS (CrispASR) synthesis failed ({(int)response.Status
- VibeVoice (CrispASR) — the crispasr server crashed during sy
- IndexTTS (CrispASR) synthesis failed ({(int)response.StatusC
- MOSS-TTS (CrispASR) request failed — the connection to the c
- MOSS-TTS (CrispASR) synthesis failed ({(int)response.StatusC
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/0fac2dbfb09dae7f.
Report an issue: GitHub.