SubtitleEdit/subtitleedit · error · HttpRequestException

DashScope task poll failed ({(int)response.StatusCode}). Res

Error message

DashScope task poll failed ({(int)response.StatusCode}). Response: {json}

What it means

Thrown when a GET request to poll the transcription task status (/api/v1/tasks/{taskId}) returns a non-success HTTP status. Polling runs in a while(true) loop with 3-second delays. Any non-2xx response (other than cancellation) immediately throws with the status code and response body.

Source

Thrown at src/ui/Features/Video/SpeechToText/DashScope/DashScopeSttService.cs:208

    }

    private async Task<string> PollTaskAsync(string taskId, CancellationToken ct)
    {
        var url = BaseUrl + TasksPath + Uri.EscapeDataString(taskId);
        var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };

        while (true)
        {
            ct.ThrowIfCancellationRequested();

            using var request = new HttpRequestMessage(HttpMethod.Get, url);
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _settings.ApiKey);

            using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);
            var json = await response.Content.ReadAsStringAsync(ct);
            if (!response.IsSuccessStatusCode)
            {
                throw new HttpRequestException($"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}");
            }

            var output = JsonSerializer.Deserialize<DashScopeTaskResponse>(json, options)?.Output;
            var status = output?.TaskStatus ?? "UNKNOWN";
            switch (status.ToUpperInvariant())
            {
                case "SUCCEEDED":
                    var transcriptionUrl = output?.Result?.TranscriptionUrl
                        ?? (output?.Results != null && output.Results.Count > 0 ? output.Results[0].TranscriptionUrl : null);
                    if (string.IsNullOrEmpty(transcriptionUrl))
                    {
                        throw new InvalidOperationException($"DashScope task succeeded but returned no transcription_url. Response: {json}");
                    }
                    return transcriptionUrl;

                case "FAILED":
                case "UNKNOWN":
                    throw new InvalidOperationException($"DashScope transcription task {status}. Response: {json}");

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Check the status code: 404 means the task ID is no longer valid; 401/403 means key issues.
  2. For transient errors (5xx, 429), add retry logic with backoff instead of immediately throwing.
  3. Verify the task was submitted to the same region/endpoint being polled.
  4. Reduce polling frequency if hitting rate limits (increase the 3-second delay).
  5. Re-run the entire transcription if the task ID is permanently gone (404).

Example fix

// before
if (!response.IsSuccessStatusCode)
{
    throw new HttpRequestException($"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}");
}

// after — retry on transient errors before giving up
if (!response.IsSuccessStatusCode)
{
    if ((int)response.StatusCode is 429 or >= 500)
    {
        await Task.Delay(TimeSpan.FromSeconds(5), ct);
        continue; // retry the poll
    }
    throw new HttpRequestException($"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}");
}
Defensive patterns

Strategy: retry

Validate before calling

// Validate task ID format before polling
if (string.IsNullOrWhiteSpace(taskId) || taskId.Length < 8)
    throw new InvalidOperationException($"Invalid task ID for polling: {taskId}");

Try / catch

try { var url = await PollTaskAsync(taskId, ct); }
catch (HttpRequestException ex) when (ex.Message.Contains("task poll failed"))
{
    var code = ExtractStatusCode(ex.Message);
    if (code is 429 or >= 500) { await Task.Delay(5000, ct); /* retry poll */ }
    else if (code == 404) /* task expired, re-submit */;
}

Prevention

When it happens

Trigger: The task ID expired or was garbage-collected by DashScope (expect 404); the API key lost permissions mid-job (expect 401/403); transient server errors (5xx); rate limiting from too-frequent polling (the loop polls every 3 seconds).

Common situations: The task was created but took so long that DashScope's task retention expired; the polling endpoint is different from the region where the task was created; network instability causes intermittent failures; the API key was revoked between submit and poll.

Related errors


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