{"record":{"id":"45ff10afbe96584a","repo":"CherryHQ/cherry-studio","slug":"dashscope-api-request-timeout-after-timeout-10","errorCode":null,"errorMessage":"DashScope API request timeout after ${timeout / 1000}s","messagePattern":"DashScope API request timeout after (.+?)s","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/provider/custom/dashscope/dashscopeTransport.ts","lineNumber":543,"sourceCode":"        ...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}\n\nexport type { DashScopeTransport }\n","sourceCodeStart":525,"sourceCodeEnd":558,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/provider/custom/dashscope/dashscopeTransport.ts#L525-L558","documentation":"Thrown when a single DashScope HTTP request is aborted by its internal `AbortController` timeout (not by an external caller abort). Each request sets a per-call timeout (120s for submit, 10s for poll, `DEFAULT_TIMEOUT` otherwise); when it elapses the fetch is aborted and, because the abort was internal, this timeout error is thrown instead of an `AbortError`.","triggerScenarios":"A submit or poll HTTP call took longer than its timeout threshold: a slow vendor response, a congested network, or a large image upload stalling.","commonSituations":"Network latency or packet loss to DashScope; vendor endpoint slow under load; a proxy between the app and the API adding latency.","solutions":["Check network connectivity and latency to the DashScope host.","Retry the request — transient slow responses often succeed on the next attempt.","If consistently slow, review whether a proxy or VPN is adding latency."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"const isDashScopeTimeout = (e: unknown): boolean =>\n  e instanceof Error && /DashScope API request timeout/.test(e.message)","tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    return await transport.submit(input)\n  } catch (e) {\n    if (e instanceof Error && /request timeout/.test(e.message) && attempt < 2) continue\n    throw e\n  }\n}","preventionTips":["Retry single-request timeouts (they are often transient)","Monitor latency to the vendor host to detect chronic slowness","Keep per-request timeouts generous enough for the largest payloads"],"tags":["timeout","network","dashscope","fetch"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}