{"record":{"id":"0f8d361726e9bff5","repo":"mastra-ai/mastra","slug":"download-assets-failed","errorCode":"DOWNLOAD_ASSETS_FAILED","errorMessage":"Failed to download asset: ${safeUrl}","messagePattern":"Failed to download asset: (.+?)","errorType":"error_code","errorClass":"MastraError","httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/message-list/prompt/download-assets.ts","lineNumber":40,"sourceCode":"\nexport const downloadFromUrl = async ({ url, downloadRetries }: { url: URL; downloadRetries: number }) => {\n  const urlText = url.toString();\n  const safeUrl = redactUrlForLog(url);\n\n  try {\n    const response = await fetchWithRetry(\n      urlText,\n      {\n        method: 'GET',\n      },\n      downloadRetries,\n      {\n        shouldRetryResponse: response => response.status >= 500,\n      },\n    );\n\n    if (!response.ok) {\n      throw new MastraError({\n        id: 'DOWNLOAD_ASSETS_FAILED',\n        text: `Failed to download asset: ${safeUrl}`,\n        domain: ErrorDomain.LLM,\n        category: ErrorCategory.USER,\n        details: { url: urlText },\n      });\n    }\n    return {\n      data: new Uint8Array(await response.arrayBuffer()),\n      mediaType: response.headers.get('content-type') ?? undefined,\n    };\n  } catch (error) {\n    throw new MastraError(\n      {\n        id: 'DOWNLOAD_ASSETS_FAILED',\n        text: `Failed to download asset: ${safeUrl}`,\n        domain: ErrorDomain.LLM,\n        category: ErrorCategory.USER,","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/message-list/prompt/download-assets.ts#L22-L58","documentation":"downloadFromUrl fetches remote assets (with retry on 5xx) before prompt conversion. If the final response is still not ok (404, 403, etc.), it throws a MastraError with id DOWNLOAD_ASSETS_FAILED containing the safe URL in the message and details. The library refuses to silently embed a failed asset.","triggerScenarios":"Calling downloadAssets (or the agent flow that does so) with an attachment/image URL that responds with a non-2xx, non-retryable status — expired signed S3/GCS URLs, removed files, private buckets, DNS-level failures surfacing as !response.ok paths after the retried fetch.","commonSituations":"Expired presigned URLs (S3 SignatureDoesNotMatch / expired token); deleted or renamed CDN objects; hotlink-protected or geo-blocked assets; wrong storage permissions.","solutions":["Verify the URL is reachable and returns 200 (curl -I the safeUrl in the error).","Regenerate expired signed URLs (S3 presigned / GCS signed URLs) before the run.","Fix storage permissions/CORS or make the object public/authenticated as needed.","Download the asset yourself and pass inline data/base64 content instead of a remote URL."],"exampleFix":"// before\n{ url: 'https://s3.amazonaws.com/bucket/img.png?X-Amz-Expires=60&...' } // expired\n// after\nconst freshUrl = await getFreshPresignedUrl('bucket', 'img.png');\n{ url: freshUrl }","handlingStrategy":"try-catch","validationCode":"async function assertAssetReachable(url: string) {\n  const res = await fetch(url, { method: 'HEAD' });\n  if (!res.ok) throw new Error(`Asset ${url} not reachable: HTTP ${res.status}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  assets = await downloadAssets([{ url }]);\n} catch (e) {\n  if (e instanceof MastraError && e.id === 'DOWNLOAD_ASSETS_FAILED') {\n    console.error(`Asset fetch failed for ${e.detail?.url}; regenerating signed URL`);\n    assets = await downloadAssets([{ url: await refreshPresignedUrl(e.detail.url) }]);\n  } else throw e;\n}","preventionTips":["Regenerate presigned URLs shortly before each run; don't cache them across sessions.","HEAD-check asset URLs before submitting them with agent messages.","Ensure storage objects are readable by the runtime's credentials."],"tags":["network","download","http","asset"],"backgroundTag":"asset-download-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}