SubtitleEdit/subtitleedit · error · HttpRequestException

STT request failed with status {statusCode} ({response.Statu

Error message

STT request failed with status {statusCode} ({response.StatusCode}) calling {safeEndpoint}. Response: {errorContent}

What it means

The OpenAI-compatible STT endpoint returned a non-2xx status. The status code is carried on the HttpRequestException (via response.StatusCode) so callers can branch on it — notably a 4xx complaining about 'model' is turned into a Model-field hint (issue #12877). The endpoint is sanitized for logging via SanitizeEndpointForLog before being written to the message or tools log.

Source

Thrown at src/ui/Features/Video/SpeechToText/OpenAiCompatible/OpenAiSttService.cs:229

                ? _settings.Temperature.ToString("F2", CultureInfo.InvariantCulture)
                : "(not sent)";
            var granularitiesSummary = _settings.Stream ? "(not sent)" : "[segment,word]";
            var paramSummary =
                $"model={_settings.Model}, language={languageToUse}, " +
                $"response_format={responseFormat}, timestamp_granularities={granularitiesSummary}, " +
                $"stream={(_settings.Stream ? "true" : "(not sent)")}, " +
                $"temperature={temperatureSummary}, " +
                $"promptLen={_settings.Prompt?.Length ?? 0}, file={fileName}";
            var safeEndpoint = SanitizeEndpointForLog(_settings.EndpointUrl);
            _settings.Logger?.Invoke(
                $"OpenAI-compatible STT failed: POST {safeEndpoint}{Environment.NewLine}" +
                $"Status: {statusCode} {response.StatusCode}{Environment.NewLine}" +
                $"RequestParams: {paramSummary}{Environment.NewLine}" +
                $"ResponseBody: {errorContent}");
            // Carry the status code on the exception: the caller turns a 4xx that
            // complains about "model" into a hint about the Model field, and
            // sniffing the number back out of the message is fragile (issue #12877).
            throw new HttpRequestException(
                $"STT request failed with status {statusCode} ({response.StatusCode}) " +
                $"calling {safeEndpoint}. Response: {errorContent}",
                null,
                response.StatusCode);
        }

        // Check if streaming (SSE)
        var contentType = response.Content.Headers.ContentType?.MediaType ?? "";
        if (contentType.Contains("text/event-stream") || response.Headers.Contains("Server-Sent-Events"))
        {
            return await ParseSseStreamAsync(response, progress, segmentProgress, cancellationToken);
        }

        // Non-streaming response
        var jsonResponse = await response.Content.ReadAsStringAsync(cancellationToken);
        return ParseJsonResponse(jsonResponse);
    }

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Read statusCode and errorContent in the message — a 4xx mentioning 'model' usually means the Model field is wrong (issue #12877).
  2. Confirm EndpointUrl is the STT transcription endpoint, not the chat endpoint.
  3. Validate/rotate the API key.
  4. Back off and retry on 429 rate limits.

Example fix

// before: chat endpoint used for STT
EndpointUrl = "https://api.example.com/v1/chat/completions";
// after: correct transcription endpoint
EndpointUrl = "https://api.example.com/v1/audio/transcriptions";
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Uri.TryCreate(_settings.EndpointUrl, UriKind.Absolute, out var uri)
    || !uri.AbsolutePath.EndsWith("/transcriptions", StringComparison.OrdinalIgnoreCase))
    return Invalid("EndpointUrl must be the /v1/audio/transcriptions URL");

Try / catch

try { return await service.TranscribeAsync(...); }
catch (HttpRequestException ex) when (ex.StatusCode is HttpStatusCode.BadRequest && ex.Message.Contains("model"))
{ /* hint: Model field is wrong (issue #12877) */ }
catch (HttpRequestException ex) when (ex.StatusCode is HttpStatusCode.Unauthorized)
{ /* API key invalid */ }

Prevention

When it happens

Trigger: Any non-success HTTP status from POST {EndpointUrl}: 400/404 about model name, 401 bad API key, 403 forbidden, 404 wrong endpoint path, 429 rate limit, 5xx server error.

Common situations: EndpointUrl points at /v1/chat/completions instead of /v1/audio/transcriptions; wrong or non-existent Model name; expired/invalid API key; rate-limited account; provider outage.

Related errors


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