{"record":{"id":"5f46fc69bf20df18","repo":"CherryHQ/cherry-studio","slug":"dashscope-api-error-response-status-errort","errorCode":null,"errorMessage":"DashScope API error: ${response.status} - ${errorText}","messagePattern":"DashScope API error: (.+?) - (.+?)","errorType":"exception","errorClass":"DashScopeApiError","httpStatus":null,"severity":"error","filePath":"src/main/ai/provider/custom/dashscope/dashscopeTransport.ts","lineNumber":537,"sourceCode":"\n    const fetchOptions: RequestInit = {\n      method,\n      headers: {\n        Authorization: `Bearer ${this.apiKey}`,\n        ...(method === 'POST' && { 'Content-Type': 'application/json' }),\n        ...options.extraHeaders\n      },\n      signal: controller.signal\n    }\n    if (method === 'POST' && body !== undefined) {\n      fetchOptions.body = JSON.stringify(body)\n    }\n\n    try {\n      const response = await fetch(`${this.baseURL}${path}`, fetchOptions)\n      if (!response.ok) {\n        const errorText = (await response.text().catch(() => '')).slice(0, 500)\n        throw new DashScopeApiError(`DashScope API error: ${response.status} - ${errorText}`, response.status)\n      }\n      return (await response.json()) as T\n    } catch (error) {\n      if (error instanceof Error && error.name === 'AbortError') {\n        if (externallyAborted) throw createAbortError('DashScope API request aborted')\n        throw new Error(`DashScope API request timeout after ${timeout / 1000}s`)\n      }\n      throw error\n    } finally {\n      clearTimeout(timeoutId)\n      externalSignal?.removeEventListener('abort', onExternalAbort)\n    }\n  }\n}\n\nexport function createDashScopeTransport(settings: DashScopeTransportSettings): DashScopeTransport {\n  return new DashScopeTransport(settings)\n}","sourceCodeStart":519,"sourceCodeEnd":555,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/provider/custom/dashscope/dashscopeTransport.ts#L519-L555","documentation":"Thrown as a `DashScopeApiError` when a fetch to DashScope returns a non-2xx HTTP status. The message includes the status code and the first 500 characters of the response body; the `statusCode` field carries the numeric HTTP status for programmatic handling. This covers auth, quota, validation, and server errors at the transport boundary.","triggerScenarios":"401/403 from a missing/invalid API key; 429 from rate/quota limits; 400 from a malformed request body; 5xx from a vendor outage. Thrown by both submit and poll requests.","commonSituations":"API key not set or revoked; exceeded DashScope QPS/concurrency; a parameter (size, n, seed) outside the model's accepted range; transient vendor 5xx during peak load.","solutions":["Read `error.statusCode`: 401/403 → fix the API key; 429 → back off and retry; 400 → inspect the body for the bad parameter; 5xx → retry with backoff.","Confirm the API key resolves via `loadApiKey` (env `DASHSCOPE_API_KEY` or settings).","For 429, reduce concurrency or space out requests."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"const isDashScopeApiError = (e: unknown): e is DashScopeApiError =>\n  e instanceof Error && e.name === 'DashScopeApiError'","tryCatchPattern":"try {\n  await transport.submit(input)\n} catch (e) {\n  if (e instanceof DashScopeApiError) {\n    if (e.statusCode === 401 || e.statusCode === 403) /* fix API key */\n    else if (e.statusCode === 429) /* back off and retry */\n    else if (e.statusCode >= 500) /* retry with backoff */\n    else /* 4xx — inspect body, fix params */\n  }\n  throw e\n}","preventionTips":["Branch on statusCode for tailored handling (auth vs quota vs validation)","Retry 429/5xx with exponential backoff","Log the first 500 chars of the body for diagnosis"],"tags":["api-error","http","dashscope","auth","quota"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}