{"record":{"id":"43532b31b80ca16a","repo":"vercel/ai","slug":"failed-to-download-url-cause","errorCode":null,"errorMessage":"Failed to download ${url}: ${cause}","messagePattern":"Failed to download (.+?): (.+?)","errorType":"exception","errorClass":"DownloadError","httpStatus":null,"severity":"error","filePath":"packages/provider-utils/src/download-blob.ts","lineNumber":54,"sourceCode":"        statusCode: response.status,\n        statusText: response.statusText,\n      });\n    }\n\n    const data = await readResponseWithSizeLimit({\n      response,\n      url,\n      maxBytes: options?.maxBytes ?? DEFAULT_MAX_DOWNLOAD_SIZE,\n    });\n\n    const contentType = response.headers.get('content-type') ?? undefined;\n    return new Blob([data], contentType ? { type: contentType } : undefined);\n  } catch (error) {\n    if (DownloadError.isInstance(error)) {\n      throw error;\n    }\n\n    throw new DownloadError({ url, cause: error });\n  }\n}\n","sourceCodeStart":36,"sourceCodeEnd":57,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/provider-utils/src/download-blob.ts#L36-L57","documentation":"downloadBlob wraps any unexpected failure during the download — network errors, DNS failures, TLS errors, aborts, or exceeding the maxBytes size limit — in a DownloadError with the original error attached as cause. This guarantees callers always receive a DownloadError while preserving the underlying reason for debugging.","triggerScenarios":"The fetch itself rejected (offline host, DNS failure, TLS certificate error, request aborted via abortSignal) or the body reader failed, e.g. the response exceeded maxBytes (default 100 MiB) or the connection dropped mid-stream.","commonSituations":"Downloading very large media files that exceed the 100 MiB default cap; air-gapped/DNS-blocked environments; self-signed certificates on internal asset hosts; user-triggered AbortSignal cancellations; firewalls blocking the asset host.","solutions":["Inspect error.cause to identify the real failure (AbortError, size-limit, DNS, TLS).","Pass a higher maxBytes option if the file legitimately exceeds the default 100 MiB limit.","Check network connectivity, DNS resolution, and TLS validity for the asset host.","Handle AbortError distinctly if you intentionally cancel downloads via abortSignal.","Retry transient network failures with backoff."],"exampleFix":"// before: default size cap\nconst blob = await downloadBlob(url);\n\n// after: allow larger files and surface the cause\ntry {\n  const blob = await downloadBlob(url, { maxBytes: 512 * 1024 * 1024 });\n} catch (e) {\n  if (DownloadError.isInstance(e)) console.error('Download failed:', e.cause);\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"const head = await fetch(url, { method: 'HEAD' });\nconst size = Number(head.headers.get('content-length') ?? 0);\nconst maxBytes = 100 * 1024 * 1024; // library default\nif (size > maxBytes) throw new Error(`File ${size} bytes exceeds ${maxBytes}; pass a larger maxBytes`);","typeGuard":"import { DownloadError } from '@ai-sdk/provider-utils';\nfunction isDownloadError(e: unknown): e is DownloadError {\n  return DownloadError.isInstance(e);\n}","tryCatchPattern":"try {\n  const blob = await downloadBlob(url, { maxBytes: 256 * 1024 * 1024 });\n} catch (error) {\n  if (DownloadError.isInstance(error)) {\n    console.error('Download failed:', error.cause); // AbortError, size limit, DNS, TLS...\n  }\n  throw error;\n}","preventionTips":["Always read error.cause to find the real failure reason.","Set maxBytes explicitly for known-large media files (default is 100 MiB).","Distinguish user-initiated aborts (AbortError) from genuine network failures.","Verify DNS/TLS reachability of asset hosts in restricted networks.","Retry transient network errors with backoff."],"tags":["network","download","size-limit","wrapped-error"],"backgroundTag":"download-failed","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}