datawhalechina/hello-agents · error · ApiError

请求超时,请稍后重试或检查后端服务

Error message

请求超时,请稍后重试或检查后端服务

What it means

Timeout branch of the typed ApiClient: a per-request AbortController timer fires, fetch rejects with a DOMException named 'AbortError', and the catch maps it to ApiError('请求超时...', 408). Seeing this means the request was aborted by the client's own timer, not by the server — the server may still be processing.

Source

Thrown at Co-creation-projects/aatanxiao12-beep-YingQian/frontend/src/api/client.ts:62

        payload &&
        typeof payload === 'object' &&
        'detail' in payload &&
        typeof (payload as { detail: unknown }).detail === 'string'
          ? (payload as { detail: string }).detail
          : payload &&
              typeof payload === 'object' &&
              'message' in payload &&
              typeof (payload as { message: unknown }).message === 'string'
            ? (payload as { message: string }).message
            : `请求失败(${res.status})`
      throw new ApiError(detail, res.status)
    }

    return payload as T
  } catch (err) {
    if (err instanceof ApiError) throw err
    if (err instanceof DOMException && err.name === 'AbortError') {
      throw new ApiError('请求超时,请稍后重试或检查后端服务', 408)
    }
    throw new ApiError(err instanceof Error ? err.message : '网络异常', 0)
  } finally {
    window.clearTimeout(timer)
  }
}

View on GitHub (pinned to 606a07d341)

Solutions

  1. Raise the timeout for slow endpoints — make timeout a per-call option instead of a constant
  2. Measure actual backend latency (server logs / browser network tab) and set the timer with headroom
  3. Distinguish user-initiated aborts from timer aborts by tagging the AbortController (e.g. controller.timerAbort = true) so only timeouts map to 408
  4. If the backend is genuinely hanging, fix the backend (add its own timeout / streaming response)

Example fix

// before
if (err instanceof DOMException && err.name === 'AbortError') {
    throw new ApiError('请求超时,请稍后重试或检查后端服务', 408)
}

// after
if (err instanceof DOMException && err.name === 'AbortError') {
    if (signal?.aborted && !timerFired) throw err; // caller-initiated abort, rethrow
    throw new ApiError('请求超时,请稍后重试或检查后端服务', 408)
}
Defensive patterns

Strategy: retry

Try / catch

try { await client.post('/slow', body, { timeout: 60000 }); } catch (e) { if (e instanceof ApiError && e.status === 408) { await sleep(2000); return retryOnce(); } throw e; }

Prevention

When it happens

Trigger: Backend endpoint slower than the configured timeout (long LLM/agent calls easily exceed typical 10-30s timers), cold-start latency of serverless backends, or a hung backend connection. Note AbortError with name 'AbortError' only — a user-driven abort would also land here unless filtered.

Common situations: AI generation endpoints that take 60s+ behind a 15s client timeout; dev server hibernation; slow mobile networks; accidental shared AbortController aborting many requests at once.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/d17ada297557fc49. Report an issue: GitHub.