PaddlePaddle/PaddleOCR · error · RequestTimeoutError

Request timed out after ${timeoutMs}ms

Error message

Request timed out after ${timeoutMs}ms

What it means

RequestTimeoutError is thrown by the low-level fetch() when the underlying fetch rejects because the per-request timeout controller aborted — the request did not complete within effectiveTimeout milliseconds. The configured timeout is exposed on `timeoutMs` and the original network error on `cause`. It fires only when the user-supplied AbortSignal did not abort first (that case rethrows the user's abort reason instead).

Source

Thrown at api_sdk/typescript/src/internal/http.ts:218

    const abort = () => abortController.abort();
    timeoutController.signal.addEventListener("abort", abort, { once: true });
    if (signal?.aborted) {
      abort();
    } else {
      signal?.addEventListener("abort", abort, { once: true });
    }
    try {
      resp = await this.fetchImpl(url, {
        ...init,
        headers,
        signal: abortController.signal,
      });
    } catch (e: unknown) {
      if (signal?.aborted) {
        throw userAbortReason(signal);
      }
      if (timeoutController.signal.aborted) {
        throw new RequestTimeoutError(effectiveTimeout, { cause: e });
      }
      const message = e instanceof Error ? e.message : String(e);
      throw new NetworkError(`Connection failed: ${message}`);
    } finally {
      clearTimeout(timeoutID);
      signal?.removeEventListener("abort", abort);
    }

    if (resp.ok) return resp;

    let text = await resp.text();
    try {
      const payload = JSON.parse(text) as { msg?: string; message?: string; errorMsg?: string };
      text = payload.msg || payload.message || payload.errorMsg || text;
    } catch {
      // Keep raw response text.
    }
    if (resp.status === 401 || resp.status === 403) {

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Pass a larger timeout: submitFile(model, path, payload, { timeoutMs: 300_000 }) or raise the SDK default
  2. Reduce payload size (downscale images, trim page ranges) so the upload fits the existing budget
  3. Retry transient slow requests — the class is designed to be retryable with backoff
  4. Check network path (proxy, VPN, DNS) if every request times out, not just large ones

Example fix

// before
const jobId = await client.submitFile(model, bigPdf, {});

// after
const jobId = await client.submitFile(model, bigPdf, {}, { timeoutMs: 5 * 60_000 });
// or for polling:
const result = await poller.waitForResult(jobId, { maxWaitTime: 10 * 60_000 });
Defensive patterns

Strategy: retry

Validate before calling

function sizeNeedsBiggerTimeout(bytes: number, bandwidthBps: number, timeoutMs: number): boolean {
  return (bytes * 8) / (bandwidthBps) * 1000 > timeoutMs * 0.8;
}

Type guard

function isRequestTimeout(e: unknown): e is RequestTimeoutError {
  return e instanceof RequestTimeoutError;
}

Try / catch

try {
  await client.submitFile(model, filePath, payload, { timeoutMs: 300_000 });
} catch (e) {
  if (e instanceof RequestTimeoutError) {
    if (e.timeoutMs >= 300_000) throw new Error("Upload too slow — reduce file size");
    return client.submitFile(model, filePath, payload, { timeoutMs: e.timeoutMs * 2 });
  }
  throw e;
}

Prevention

When it happens

Trigger: Any HTTP call where the server or network is slower than the effective timeout: uploading a very large file to submitFile on a slow link, polling a status endpoint behind a slow proxy, or a default timeout that is too small for big payloads. The poller passes its remaining wait budget as timeoutMs, so long-poll loops near their deadline also hit this.

Common situations: Default request timeout too low for 50+ MB PDF uploads; high-latency regions far from the API endpoint; mobile/flaky networks; cold-start backends that take seconds to respond; containers with constrained bandwidth.

Understand the failure class

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/a3bf27fe9cb21d73. Report an issue: GitHub.