SubtitleEdit/subtitleedit · error · HttpRequestException
DashScope upload-policy request failed ({(int)policyResponse
Error message
DashScope upload-policy request failed ({(int)policyResponse.StatusCode}). Response: {err} What it means
Thrown when the GET request to DashScope's upload-policy endpoint (/api/v1/uploads?action=getPolicy&model=...) returns a non-success HTTP status code. The policy is the first step of the pipeline — without it, the OSS upload cannot proceed. The status code and full response body are included in the message and logged.
Source
Thrown at src/ui/Features/Video/SpeechToText/DashScope/DashScopeSttService.cs:123
/// <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)
{
var err = await policyResponse.Content.ReadAsStringAsync(ct);
_settings.Logger?.Invoke($"DashScope upload-policy request failed: GET {policyUrl} => {(int)policyResponse.StatusCode}: {err}");
throw new HttpRequestException($"DashScope upload-policy request failed ({(int)policyResponse.StatusCode}). Response: {err}");
}
var policyJson = await policyResponse.Content.ReadAsStringAsync(ct);
var policy = JsonSerializer.Deserialize<DashScopeUploadPolicyResponse>(policyJson,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true })?.Data;
if (policy == null)
{
_settings.Logger?.Invoke($"DashScope upload-policy response could not be parsed: {policyJson}");
throw new InvalidOperationException($"DashScope upload-policy response could not be parsed. Response: {policyJson}");
}
var key = $"{policy.UploadDir}/{fileName}";
using var form = new MultipartFormDataContent
{
{ new StringContent(policy.OssAccessKeyId), "OSSAccessKeyId" },
{ new StringContent(policy.Policy), "policy" },
{ new StringContent(policy.Signature), "Signature" },View on GitHub (pinned to 17a9f07487)
Solutions
- Check the HTTP status code in the error: 401/403 means the API key is wrong or expired — regenerate and re-enter it.
- Verify the region setting matches the API key's account region (china vs international base URL).
- Confirm the ASR model is enabled and available in the DashScope console for your account.
- Test the API key with a simple curl: curl -H 'Authorization: Bearer <key>' '<policyUrl>'.
- If 5xx, retry after a short delay — DashScope may be experiencing a transient outage.
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate API key and region before the pipeline starts
if (string.IsNullOrWhiteSpace(_settings.ApiKey))
throw new InvalidOperationException("DashScope API key is not set.");
var expectedBaseUrl = DashScopeSttService.GetBaseUrl(_settings.Region);
if (_settings.Region != "china" && !expectedBaseUrl.Contains("intl"))
throw new InvalidOperationException($"Region '{_settings.Region}' may not match the API key's account region."); Try / catch
try { var policy = await GetUploadPolicy(ct); }
catch (HttpRequestException ex) when (ex.Message.Contains("upload-policy request failed"))
{
var code = ExtractStatusCode(ex.Message);
if (code == 401 || code == 403) /* re-prompt for API key */;
else if (code >= 500) /* retry with backoff */;
} Prevention
- Store the API key securely and validate it is non-empty before transcription.
- Match the region setting (china/international) to the API key's account region.
- Confirm the ASR model is enabled in the DashScope console.
- Test the API key with a minimal curl request before integrating.
When it happens
Trigger: The Bearer token (_settings.ApiKey) is missing, expired, or invalid (expect 401/403); the model name is wrong or not enabled for the account (expect 400); the DashScope API endpoint is unreachable or returns 5xx; the region setting (china vs international) is wrong, hitting the wrong base URL.
Common situations: API key was regenerated on the DashScope console but not updated in settings; using the international base URL with a China-only key or vice versa; the model name 'qwen3-asr-flash-filetrans' is not yet available in the selected region; account has insufficient quota or the ASR service is not activated; network firewall blocks the DashScope API host.
Related errors
- DashScope OSS upload failed ({(int)uploadResponse.StatusCode
- DashScope async submit failed ({(int)response.StatusCode}).
- DashScope task poll failed ({(int)response.StatusCode}). Res
- DashScope transcription timed out after {_settings.TimeoutSe
- STT request failed with status {statusCode} ({response.Statu
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/81586bc11d512d94.
Report an issue: GitHub.