SubtitleEdit/subtitleedit · error · TimeoutException
DashScope transcription timed out after {_settings.TimeoutSe
Error message
DashScope transcription timed out after {_settings.TimeoutSeconds} seconds. What it means
Thrown when the DashScope speech-to-text pipeline's internal timeout (TimeoutSeconds setting) fires via a linked CancellationTokenSource, distinct from a user-initiated cancel. The catch guard `when (!cancellationToken.IsCancellationRequested)` ensures only the timeout CTS (not user cancel) triggers this TimeoutException. The pipeline includes upload, submit, and polling steps, any of which can exceed the timeout.
Source
Thrown at src/ui/Features/Video/SpeechToText/DashScope/DashScopeSttService.cs:102
progress?.Report("Submitting transcription task...");
_settings.Logger?.Invoke($"DashScope: submitting async task for {ossUrl}");
var taskId = await SubmitTaskAsync(ossUrl, language, ct);
progress?.Report("Waiting for transcription to complete...");
var transcriptionUrl = await PollTaskAsync(taskId, ct);
_settings.Logger?.Invoke($"DashScope: fetching result from {transcriptionUrl}");
using var resultResponse = await _httpClient.GetAsync(transcriptionUrl, HttpCompletionOption.ResponseHeadersRead, ct);
resultResponse.EnsureSuccessStatusCode();
var resultJson = await resultResponse.Content.ReadAsStringAsync(ct);
return ParseTranscriptionResult(resultJson);
}
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
{
// Our own timeout fired, not a user cancel — surface it as an error
// so the caller doesn't mistake it for cancellation.
throw new TimeoutException($"DashScope transcription timed out after {_settings.TimeoutSeconds} seconds.");
}
}
/// <summary>
/// Upload the audio to DashScope temporary storage and return its
/// <c>oss://</c> URL. Two steps: fetch an upload policy, then POST the file
/// to the returned OSS host with the signed form fields (file field last).
/// </summary>
private async Task<string> UploadFileAsync(byte[] audioBytes, string fileName, CancellationToken ct)
{
var model = string.IsNullOrWhiteSpace(_settings.Model) ? "qwen3-asr-flash-filetrans" : _settings.Model;
var policyUrl = $"{BaseUrl}{UploadsPath}?action=getPolicy&model={Uri.EscapeDataString(model)}";
using var policyRequest = new HttpRequestMessage(HttpMethod.Get, policyUrl);
policyRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _settings.ApiKey);
using var policyResponse = await _httpClient.SendAsync(policyRequest, HttpCompletionOption.ResponseHeadersRead, ct);
if (!policyResponse.IsSuccessStatusCode)
{View on GitHub (pinned to 17a9f07487)
Solutions
- Increase _settings.TimeoutSeconds to accommodate the audio length (rough rule: 1-2 minutes per 10 minutes of audio for the polling phase).
- Set TimeoutSeconds to 0 to disable the internal timeout entirely and rely only on user cancellation.
- Pre-split long audio files into shorter segments before submission.
- Check DashScope's status page for queue delays if timeouts are intermittent.
- Verify network bandwidth is sufficient for the upload step (audio is uploaded in full before processing begins).
Defensive patterns
Strategy: validation
Validate before calling
// Scale the timeout to audio duration before starting
var audioDurationSeconds = GetAudioDuration(audioFilePath);
var minTimeout = (int)(audioDurationSeconds * 0.5) + 120; // 50% of audio + 2 min overhead
if (_settings.TimeoutSeconds > 0 && _settings.TimeoutSeconds < minTimeout)
_settings = _settings with { TimeoutSeconds = minTimeout }; Try / catch
try { return await service.TranscribeAsync(audioPath, language, progress, segProgress, ct); }
catch (TimeoutException ex) when (ex.Message.Contains("DashScope"))
{ /* increase TimeoutSeconds, re-split audio, or retry */ } Prevention
- Set TimeoutSeconds proportional to the audio file duration (at least 1 minute per 10 minutes of audio).
- Set TimeoutSeconds to 0 to disable internal timeouts for very long files.
- Pre-split long audio into shorter segments before transcription.
- Monitor DashScope's processing time for typical audio lengths and adjust the setting accordingly.
When it happens
Trigger: TimeoutSeconds > 0 is set and the linked CTS cancels during UploadFileAsync, SubmitTaskAsync, PollTaskAsync, or the result download — while the user's own cancellationToken has not been cancelled. Common during long audio files where the polling loop (3-second intervals) runs for minutes.
Common situations: Transcribing a long audio file (30+ minutes) with a low TimeoutSeconds setting; DashScope's task queue is slow and polling takes longer than expected; the upload step is slow on a constrained network; TimeoutSeconds was left at a default that's too low for production audio lengths.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- DashScope upload-policy request failed ({(int)policyResponse
- DashScope OSS upload failed ({(int)uploadResponse.StatusCode
- DashScope async submit failed ({(int)response.StatusCode}).
- DashScope task poll failed ({(int)response.StatusCode}). Res
- STT request timed out after {_settings.TimeoutSeconds} secon
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/1f79cb76fd280395.
Report an issue: GitHub.