mastra-ai/mastra · error

Invalid URL: ${attachment.url}

Error message

Invalid URL: ${attachment.url}

What it means

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.

Source

Thrown at packages/core/src/agent/message-list/prompt/attachments-to-parts.ts:41

      parts.push({
        type: 'file',
        data: attachment.url,
        mimeType: attachment.contentType || 'application/octet-stream',
      });
      continue;
    }

    // If it's raw data (base64), convert it to a data URI
    let urlString = attachment.url;
    if (categorized.type === 'raw') {
      urlString = createDataUri(attachment.url, attachment.contentType || 'application/octet-stream');
    }

    let url;
    try {
      url = new URL(urlString);
    } catch {
      throw new Error(`Invalid URL: ${attachment.url}`);
    }

    switch (url.protocol) {
      case 'http:':
      case 'https:':
      // Cloud storage protocols supported by AI providers (e.g., Vertex AI for gs://, Bedrock for s3://)
      case 'gs:':
      case 's3:': {
        if (attachment.contentType?.startsWith('image/')) {
          parts.push({ type: 'image', image: url.toString(), mimeType: attachment.contentType });
        } else {
          if (!attachment.contentType) {
            throw new Error('If the attachment is not an image, it must specify a content type');
          }

          parts.push({
            type: 'file',
            data: url.toString(),

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Prepend a scheme to the string, e.g. 'https://' + value, before creating the attachment.
  2. Encode the URL properly with encodeURI/encodeURIComponent for spaces and special characters.
  3. For local files, read them yourself and pass data: URLs (base64 data content) or binary parts instead of file paths.
  4. Validate attachment URLs with new URL() at the UI/validation layer before sending to the agent.

Example fix

// before
{ url: 'example.com/cat.png' }
// after
{ url: 'https://example.com/cat.png' }
Defensive patterns

Strategy: validation

Validate before calling

function assertHttpUrl(u: string) {
  const url = new URL(u); // throws like the library does
  if (!['http:', 'https:', 'data:', 'gs:', 's3:'].includes(url.protocol)) {
    throw new Error(`Unsupported protocol ${url.protocol}`);
  }
}

Type guard

function isParsableUrl(u: unknown): u is string {
  if (typeof u !== 'string') return false;
  try { new URL(u); return true; } catch { return false; }
}

Try / catch

try {
  messageList.add({ role: 'user', content: [{ type: 'image', image: attachment.url }] });
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Invalid URL:')) {
    notifyUser(`Attachment URL "${attachment.url}" is malformed; include a scheme like https://`);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/25f62a56163a1ed3. Report an issue: GitHub.