PaddlePaddle/PaddleOCR · error · Error

Failed to download ${asset.url}: HTTP ${String(response.stat

Error message

Failed to download ${asset.url}: HTTP ${String(response.status)}

What it means

Thrown by loadModelAsset() when fetching the asset URL returns a non-ok HTTP status. Model bundles are plain fetch() downloads, so 404/403/5xx surface here with the exact status code. The URL is whatever resolved from the asset (built-in preset URL or custom { url }), so this usually means a wrong URL, missing CORS permission, or an offline/broken host.

Source

Thrown at paddleocr-js/packages/core/src/resources/model-asset.ts:135

}

export function assertModelResources(kind: string, resources: Record<string, unknown>): void {
  for (const [slot, value] of Object.entries(resources)) {
    assertModelResourceSlot(kind, slot, value);
  }
}

// --- Model loading (fetch + tar extraction) ---

import { extractTarEntries, pickTarEntry } from "./tar";

export async function loadModelAsset(
  asset: ModelAsset,
  fetchImpl: typeof fetch = fetch
): Promise<ModelLoadResult> {
  const response = await fetchImpl(asset.url);
  if (!response.ok) {
    throw new Error(`Failed to download ${asset.url}: HTTP ${String(response.status)}`);
  }
  const buffer = await response.arrayBuffer();
  const entries = extractTarEntries(buffer);
  const modelBytes = pickTarEntry(entries, MODEL_ENTRY_PATHS.model);
  const configBytes = pickTarEntry(entries, MODEL_ENTRY_PATHS.config);

  return {
    modelBytes,
    configText: new TextDecoder().decode(configBytes),
    download: {
      url: asset.url,
      bytes: buffer.byteLength
    }
  };
}

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Open the URL directly in a browser/curl and confirm it returns the tar (check status and content-type)
  2. If self-hosting, set CORS headers (Access-Control-Allow-Origin) on the asset host
  3. Pin a stable URL for the exact package version you depend on
  4. Add retry with backoff for transient 5xx/429, and cache successful downloads (Cache-Control / service worker)

Example fix

# before
# URL 404s
assets: { det: { url: "https://cdn.example.com/det-v99.tar" } }

# after
# verified URL + CORS enabled on host
assets: { det: { url: "https://cdn.example.com/paddleocr/det-v4.tar" } }
Defensive patterns

Strategy: retry

Validate before calling

async function urlIsFetchable(url: string): Promise<boolean> {
  try {
    const res = await fetch(url, { method: "HEAD" });
    return res.ok;
  } catch { return false; }
}

Try / catch

async function loadWithRetry(asset: ModelAsset, attempts = 3): Promise<ModelLoadResult> {
  for (let i = 0; i < attempts; i++) {
    try {
      return await loadModelAsset(asset);
    } catch (e) {
      if (e instanceof Error && /HTTP (5\d\d|429)/.test(e.message) && i < attempts - 1) {
        await new Promise(r => setTimeout(r, 2 ** i * 500));
        continue;
      }
      throw e; // 404/403 are not retried
    }
  }
  throw new Error("unreachable");
}

Prevention

When it happens

Trigger: assets: { det: { url: "https://host/det.tar" } } where the host returns 404; CDN link with a stale version segment; self-hosted bundle without CORS headers causing an opaque error; intranet host unreachable from the browser; GitHub raw/Releases links hitting rate limits (403/429).

Common situations: Hardcoded version URLs after a release moves files; hosting on object storage without setting Access-Control-Allow-Origin; corporate proxies blocking the CDN; typos in the URL path.

Related errors


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