{"record":{"id":"a49ef5bb20ba5370","repo":"CherryHQ/cherry-studio","slug":"task-polling-timeout","errorCode":null,"errorMessage":"Task polling timeout","messagePattern":"Task polling timeout","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/provider/custom/dashscope/dashscopeTransport.ts","lineNumber":494,"sourceCode":"        if (error instanceof DashScopeApiError && isTerminalHttpStatus(error.statusCode)) throw error\n\n        transientRetries++\n        if (transientRetries >= maxTransientRetries) {\n          throw error instanceof Error ? error : new Error(String(error))\n        }\n        const elapsedTime = Date.now() - startTime\n        const pollDelay = interval ?? (elapsedTime < 60000 ? 3000 : 10000)\n        await waitWithSignal(pollDelay, signal)\n        continue\n      }\n\n      const elapsedTime = Date.now() - startTime\n      const pollDelay = interval ?? (elapsedTime < 60000 ? 3000 : 10000)\n      await waitWithSignal(pollDelay, signal)\n      attempts++\n    }\n\n    throw new Error('Task polling timeout')\n  }\n\n  private async request<T>(\n    path: string,\n    method: 'POST' | 'GET',\n    body: Record<string, unknown> | undefined,\n    options: { timeout?: number; signal?: AbortSignal; extraHeaders?: Record<string, string> }\n  ): Promise<T> {\n    const timeout = options.timeout ?? DEFAULT_TIMEOUT\n    const externalSignal = options.signal\n    const controller = new AbortController()\n    let externallyAborted = false\n\n    const timeoutId = setTimeout(() => controller.abort(), timeout)\n    const onExternalAbort = () => {\n      externallyAborted = true\n      controller.abort()\n    }","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/provider/custom/dashscope/dashscopeTransport.ts#L476-L512","documentation":"Thrown by `DashScopeTransport.pollTaskResult` after exceeding `maxAttempts` (default 120) polls without the task reaching `SUCCEEDED`. The poll interval scales from 3s (first 60s) to 10s, so the default budget is roughly 15–20 minutes. This is a budget exhaustion, not a vendor failure.","triggerScenarios":"A DashScope async task that never completes within the polling window: a very slow model, a stuck PENDING/RUNNING task, or repeated transient poll failures consuming the retry budget without progress.","commonSituations":"Heavy model under load; network latency inflating poll round-trips; a task queued behind many others on the vendor side; repeated 5xx/429 polls eating into transient retries before maxAttempts.","solutions":["Increase `maxAttempts` / `interval` in the poll options to extend the budget for slow models.","Check network connectivity to `dashscope.aliyuncs.com` and retry the generation.","If the task is consistently stuck at PENDING, verify the model is available and the account is not throttled."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const POLL_OPTIONS = { maxAttempts: 180, interval: 5000 } // extend budget for slow models","typeGuard":null,"tryCatchPattern":"try {\n  urls = await transport.poll(taskId, { ...opts, maxAttempts: 180 })\n} catch (e) {\n  if (e instanceof Error && e.message === 'Task polling timeout') {\n    // resubmit or surface a 'generation is taking too long' message\n  }\n  throw e\n}","preventionTips":["Size maxAttempts/interval to the slowest supported model","Treat timeout as retriable — resubmit rather than hard-failing","Monitor network latency to the vendor host"],"tags":["timeout","polling","dashscope","async"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}