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
- Open the URL directly in a browser/curl and confirm it returns the tar (check status and content-type)
- If self-hosting, set CORS headers (Access-Control-Allow-Origin) on the asset host
- Pin a stable URL for the exact package version you depend on
- 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
- Enable CORS on self-hosted asset buckets
- Pin URLs to exact released versions
- HEAD-check model URLs in CI/deployment health checks
- Cache model downloads (HTTP caching or service worker) to avoid repeat fetches
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
- Request timed out after ${timeoutMs}ms
- PaddleOCR.js requires an HTTP(S) origin so model assets can
- Either fileUrl or filePath is required.
- OCR result item is missing result.ocrResults.
- OCR result page is missing prunedResult.
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/78202beb7155b1be.
Report an issue: GitHub.