{"record":{"id":"25f62a56163a1ed3","repo":"mastra-ai/mastra","slug":"invalid-url-attachment-url","errorCode":null,"errorMessage":"Invalid URL: ${attachment.url}","messagePattern":"Invalid URL: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/agent/message-list/prompt/attachments-to-parts.ts","lineNumber":41,"sourceCode":"      parts.push({\n        type: 'file',\n        data: attachment.url,\n        mimeType: attachment.contentType || 'application/octet-stream',\n      });\n      continue;\n    }\n\n    // If it's raw data (base64), convert it to a data URI\n    let urlString = attachment.url;\n    if (categorized.type === 'raw') {\n      urlString = createDataUri(attachment.url, attachment.contentType || 'application/octet-stream');\n    }\n\n    let url;\n    try {\n      url = new URL(urlString);\n    } catch {\n      throw new Error(`Invalid URL: ${attachment.url}`);\n    }\n\n    switch (url.protocol) {\n      case 'http:':\n      case 'https:':\n      // Cloud storage protocols supported by AI providers (e.g., Vertex AI for gs://, Bedrock for s3://)\n      case 'gs:':\n      case 's3:': {\n        if (attachment.contentType?.startsWith('image/')) {\n          parts.push({ type: 'image', image: url.toString(), mimeType: attachment.contentType });\n        } else {\n          if (!attachment.contentType) {\n            throw new Error('If the attachment is not an image, it must specify a content type');\n          }\n\n          parts.push({\n            type: 'file',\n            data: url.toString(),","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/agent/message-list/prompt/attachments-to-parts.ts#L23-L59","documentation":"attachmentsToParts parses each attachment URL with new URL() before mapping it to an AI-SDK content part. If the URL string cannot be parsed (malformed scheme, missing protocol, spaces, etc.), a plain Error 'Invalid URL: <url>' is thrown, because the rest of the function branches on url.protocol and cannot proceed.","triggerScenarios":"Adding a user message via MessageList user content conversion with an attachment whose url field is not a parseable URL string — e.g. 'example.com/img.png' (no scheme), 'htp://...', or a URL containing unencoded spaces/special characters.","commonSituations":"Users pasting bare domains without http(s):// into chat UIs; frontend code passing file paths like '/uploads/x.png' as attachment URLs; environment misconfig producing empty or partial base URLs.","solutions":["Prepend a scheme to the string, e.g. 'https://' + value, before creating the attachment.","Encode the URL properly with encodeURI/encodeURIComponent for spaces and special characters.","For local files, read them yourself and pass data: URLs (base64 data content) or binary parts instead of file paths.","Validate attachment URLs with new URL() at the UI/validation layer before sending to the agent."],"exampleFix":"// before\n{ url: 'example.com/cat.png' }\n// after\n{ url: 'https://example.com/cat.png' }","handlingStrategy":"validation","validationCode":"function assertHttpUrl(u: string) {\n  const url = new URL(u); // throws like the library does\n  if (!['http:', 'https:', 'data:', 'gs:', 's3:'].includes(url.protocol)) {\n    throw new Error(`Unsupported protocol ${url.protocol}`);\n  }\n}","typeGuard":"function isParsableUrl(u: unknown): u is string {\n  if (typeof u !== 'string') return false;\n  try { new URL(u); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  messageList.add({ role: 'user', content: [{ type: 'image', image: attachment.url }] });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Invalid URL:')) {\n    notifyUser(`Attachment URL \"${attachment.url}\" is malformed; include a scheme like https://`);\n  } else throw e;\n}","preventionTips":["Validate attachment URLs with new URL() at the UI/API boundary before submitting.","Require a scheme in input fields; auto-prefix https:// for bare domains.","Encode user-supplied URLs with encodeURI before attaching."],"tags":["url","attachment","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}