mastra-ai/mastra · error

Unsupported URL protocol: ${url.protocol}

Error message

Unsupported URL protocol: ${url.protocol}

What it means

attachmentsToParts only supports URL schemes the AI providers accept: http:, https:, and cloud-storage schemes data/fetch families plus gs: and s3:. Any other protocol falls into the default branch and throws 'Unsupported URL protocol: <protocol>'.

Source

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

            mimeType: attachment.contentType,
          });
        } else {
          if (!attachment.contentType) {
            throw new Error('If the attachment is not an image or text, it must specify a content type');
          }

          parts.push({
            type: 'file',
            data: urlString,
            mimeType: attachment.contentType,
          });
        }

        break;
      }

      default: {
        throw new Error(`Unsupported URL protocol: ${url.protocol}`);
      }
    }
  }

  return parts;
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Convert blob:/file: references to http(s) URLs or inline data: URLs (base64) before adding the message.
  2. For local files, read bytes yourself and pass them as binary/data content instead of a file:// URL.
  3. Upload the asset to accessible storage (S3/GCS/HTTP) and reference it with a supported scheme.
  4. Allowlist supported schemes (http:, https:, data:, gs:, s3:) in your app's attachment validation.

Example fix

// before
{ url: 'file:///tmp/cat.png' }
// after
{ url: 'data:image/png;base64,' + fs.readFileSync('/tmp/cat.png').toString('base64') }
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = new Set(['http:', 'https:', 'data:', 'gs:', 's3:']);
function assertSupportedProtocol(u: string) {
  const p = new URL(u).protocol;
  if (!SUPPORTED.has(p)) throw new Error(`Protocol ${p} not supported; use http/https/data/gs/s3`);
}

Type guard

function hasSupportedProtocol(u: string): boolean {
  try { return ['http:', 'https:', 'data:', 'gs:', 's3:'].includes(new URL(u).protocol); }
  catch { return false; }
}

Try / catch

try {
  messageList.add(toUserContent(attachment));
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unsupported URL protocol:')) {
    const inlined = await inlineAsDataUrl(attachment.url); // read blob/file locally
    messageList.add(toUserContent({ ...attachment, url: inlined }));
  } else throw e;
}

Prevention

When it happens

Trigger: Adding an attachment whose URL uses an unsupported scheme — e.g. file:///home/user/cat.png, ftp://..., blob:https://..., or chrome:// — when converting user content to AI SDK parts.

Common situations: Browser apps accidentally passing blob: URLs created by URL.createObjectURL; Node code passing local filesystem paths as file:// URLs; internal CDNs on custom schemes.

Related errors


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