{"record":{"id":"78202beb7155b1be","repo":"PaddlePaddle/PaddleOCR","slug":"failed-to-download-asset-url-http-string-res","errorCode":null,"errorMessage":"Failed to download ${asset.url}: HTTP ${String(response.status)}","messagePattern":"Failed to download (.+?): HTTP (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"paddleocr-js/packages/core/src/resources/model-asset.ts","lineNumber":135,"sourceCode":"}\n\nexport function assertModelResources(kind: string, resources: Record<string, unknown>): void {\n  for (const [slot, value] of Object.entries(resources)) {\n    assertModelResourceSlot(kind, slot, value);\n  }\n}\n\n// --- Model loading (fetch + tar extraction) ---\n\nimport { extractTarEntries, pickTarEntry } from \"./tar\";\n\nexport async function loadModelAsset(\n  asset: ModelAsset,\n  fetchImpl: typeof fetch = fetch\n): Promise<ModelLoadResult> {\n  const response = await fetchImpl(asset.url);\n  if (!response.ok) {\n    throw new Error(`Failed to download ${asset.url}: HTTP ${String(response.status)}`);\n  }\n  const buffer = await response.arrayBuffer();\n  const entries = extractTarEntries(buffer);\n  const modelBytes = pickTarEntry(entries, MODEL_ENTRY_PATHS.model);\n  const configBytes = pickTarEntry(entries, MODEL_ENTRY_PATHS.config);\n\n  return {\n    modelBytes,\n    configText: new TextDecoder().decode(configBytes),\n    download: {\n      url: asset.url,\n      bytes: buffer.byteLength\n    }\n  };\n}\n","sourceCodeStart":117,"sourceCodeEnd":151,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/resources/model-asset.ts#L117-L151","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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)"],"exampleFix":"# before\n# URL 404s\nassets: { det: { url: \"https://cdn.example.com/det-v99.tar\" } }\n\n# after\n# verified URL + CORS enabled on host\nassets: { det: { url: \"https://cdn.example.com/paddleocr/det-v4.tar\" } }","handlingStrategy":"retry","validationCode":"async function urlIsFetchable(url: string): Promise<boolean> {\n  try {\n    const res = await fetch(url, { method: \"HEAD\" });\n    return res.ok;\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"async function loadWithRetry(asset: ModelAsset, attempts = 3): Promise<ModelLoadResult> {\n  for (let i = 0; i < attempts; i++) {\n    try {\n      return await loadModelAsset(asset);\n    } catch (e) {\n      if (e instanceof Error && /HTTP (5\\d\\d|429)/.test(e.message) && i < attempts - 1) {\n        await new Promise(r => setTimeout(r, 2 ** i * 500));\n        continue;\n      }\n      throw e; // 404/403 are not retried\n    }\n  }\n  throw new Error(\"unreachable\");\n}","preventionTips":["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"],"tags":["network","http","model-assets","cors"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}