{"record":{"id":"4cf55f644774090c","repo":"SubtitleEdit/subtitleedit","slug":"dashscope-task-poll-failed-int-response-statusc","errorCode":null,"errorMessage":"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}","messagePattern":"DashScope task poll failed \\((.+?)\\)\\. Response: (.+?)","errorType":"http","errorClass":"HttpRequestException","httpStatus":null,"severity":"error","filePath":"src/ui/Features/Video/SpeechToText/DashScope/DashScopeSttService.cs","lineNumber":208,"sourceCode":"    }\n\n    private async Task<string> PollTaskAsync(string taskId, CancellationToken ct)\n    {\n        var url = BaseUrl + TasksPath + Uri.EscapeDataString(taskId);\n        var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };\n\n        while (true)\n        {\n            ct.ThrowIfCancellationRequested();\n\n            using var request = new HttpRequestMessage(HttpMethod.Get, url);\n            request.Headers.Authorization = new AuthenticationHeaderValue(\"Bearer\", _settings.ApiKey);\n\n            using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);\n            var json = await response.Content.ReadAsStringAsync(ct);\n            if (!response.IsSuccessStatusCode)\n            {\n                throw new HttpRequestException($\"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}\");\n            }\n\n            var output = JsonSerializer.Deserialize<DashScopeTaskResponse>(json, options)?.Output;\n            var status = output?.TaskStatus ?? \"UNKNOWN\";\n            switch (status.ToUpperInvariant())\n            {\n                case \"SUCCEEDED\":\n                    var transcriptionUrl = output?.Result?.TranscriptionUrl\n                        ?? (output?.Results != null && output.Results.Count > 0 ? output.Results[0].TranscriptionUrl : null);\n                    if (string.IsNullOrEmpty(transcriptionUrl))\n                    {\n                        throw new InvalidOperationException($\"DashScope task succeeded but returned no transcription_url. Response: {json}\");\n                    }\n                    return transcriptionUrl;\n\n                case \"FAILED\":\n                case \"UNKNOWN\":\n                    throw new InvalidOperationException($\"DashScope transcription task {status}. Response: {json}\");","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Features/Video/SpeechToText/DashScope/DashScopeSttService.cs#L190-L226","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the status code: 404 means the task ID is no longer valid; 401/403 means key issues.","For transient errors (5xx, 429), add retry logic with backoff instead of immediately throwing.","Verify the task was submitted to the same region/endpoint being polled.","Reduce polling frequency if hitting rate limits (increase the 3-second delay).","Re-run the entire transcription if the task ID is permanently gone (404)."],"exampleFix":"// before\nif (!response.IsSuccessStatusCode)\n{\n    throw new HttpRequestException($\"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}\");\n}\n\n// after — retry on transient errors before giving up\nif (!response.IsSuccessStatusCode)\n{\n    if ((int)response.StatusCode is 429 or >= 500)\n    {\n        await Task.Delay(TimeSpan.FromSeconds(5), ct);\n        continue; // retry the poll\n    }\n    throw new HttpRequestException($\"DashScope task poll failed ({(int)response.StatusCode}). Response: {json}\");\n}","handlingStrategy":"retry","validationCode":"// Validate task ID format before polling\nif (string.IsNullOrWhiteSpace(taskId) || taskId.Length < 8)\n    throw new InvalidOperationException($\"Invalid task ID for polling: {taskId}\");","typeGuard":null,"tryCatchPattern":"try { var url = await PollTaskAsync(taskId, ct); }\ncatch (HttpRequestException ex) when (ex.Message.Contains(\"task poll failed\"))\n{\n    var code = ExtractStatusCode(ex.Message);\n    if (code is 429 or >= 500) { await Task.Delay(5000, ct); /* retry poll */ }\n    else if (code == 404) /* task expired, re-submit */;\n}","preventionTips":["Implement retry with backoff for transient poll failures (429, 5xx) instead of immediate throw.","Keep the polling interval reasonable (3 seconds is already conservative).","Ensure the task is polled on the same endpoint/region it was submitted to.","Handle 404 gracefully by re-submitting the transcription task."],"tags":["network","http","dashscope","speech-to-text","polling"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}