SubtitleEdit/subtitleedit · error · HttpRequestException

AllTalk TTS server returned error {(int)result.StatusCode} (

Error message

AllTalk TTS server returned error {(int)result.StatusCode} ({result.StatusCode}).

What it means

HttpRequestException thrown after a successful transport-level response when result.IsSuccessStatusCode is false. The error body is read and logged, and the thrown message includes the numeric and symbolic status code so the user knows the server rejected the request.

Source

Thrown at src/ui/Logic/Download/TtsDownloadService.cs:178

        }
        catch (HttpRequestException ex)
        {
            SeLogger.Error(ex, "AllTalk TTS server connection failed.");
            throw new HttpRequestException("AllTalk TTS server is not reachable. Please check that the server is running.", ex);
        }
        catch (TaskCanceledException ex) when (!cancellationToken.IsCancellationRequested)
        {
            SeLogger.Error(ex, "AllTalk TTS server request timed out.");
            throw new HttpRequestException("AllTalk TTS server request timed out. Please check that the server is running.", ex);
        }

        using (result)
        {
            if (!result.IsSuccessStatusCode)
            {
                var errorBody = await result.Content.ReadAsStringAsync(cancellationToken);
                SeLogger.Error($"AllTalk TTS failed calling API at {_httpClient.BaseAddress}: Status code={result.StatusCode}" + Environment.NewLine + errorBody);
                throw new HttpRequestException($"AllTalk TTS server returned error {(int)result.StatusCode} ({result.StatusCode}).");
            }

            var bytes = await result.Content.ReadAsByteArrayAsync(cancellationToken);
            var resultJson = Encoding.UTF8.GetString(bytes);

            var jsonParser = new SeJsonParser();
            var allTalkOutput = jsonParser.GetFirstObject(resultJson, "output_file_path");
            return allTalkOutput.Replace("\\\\", "\\");
        }
    }

    public async Task<bool> AllTalkIsInstalled()
    {
        // The old Task.WhenAny check reported "installed" whenever the request completed before
        // the 2 s timeout - including completing by *faulting*, so a connection refused (server
        // not running, ~instant) counted as installed and generation failed later instead.
        try
        {

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Inspect the SeLogger entry for the full errorBody to see the server's reason.
  2. Verify the multipart fields sent match the AllTalk API version in use.
  3. Confirm the requested voice/language is valid on the server.
  4. Update AllTalk to a compatible version or align the payload to its current API.
Defensive patterns

Strategy: try-catch

Validate before calling

var url = Se.Settings.Video.TextToSpeech.AllTalkUrl.TrimEnd('/') + "/api/tts-generate";
// sanity-check required form fields before sending
if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(voice))
{
    throw new ArgumentException("AllTalk requires non-empty text and voice.");
}

Try / catch

try { var audio = await ttsService.GenerateAllTalk(...); }
catch (HttpRequestException ex) when (ex.Message.Contains("server returned error"))
{
    // read SeLogger for the server's errorBody; show status code to the user
}

Prevention

When it happens

Trigger: AllTalk /api/tts-generate returns a non-2xx (e.g. 400/401/500). errorBody is captured into the log; the thrown exception carries only the status code.

Common situations: Malformed multipart payload, missing required form fields (text/voice/language), server-side model error, expired autoplay_volume, or an AllTalk version that changed the API contract.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/9b25e34764153820. Report an issue: GitHub.