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
- Convert blob:/file: references to http(s) URLs or inline data: URLs (base64) before adding the message.
- For local files, read bytes yourself and pass them as binary/data content instead of a file:// URL.
- Upload the asset to accessible storage (S3/GCS/HTTP) and reference it with a supported scheme.
- 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
- Convert blob: URLs to data: URLs before sending to the server (createObjectURL outputs are not fetchable server-side).
- Upload local files to accessible storage and reference via https://.
- Allowlist supported schemes in your attachment validation layer.
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
- Invalid URL: ${attachment.url}
- Invalid route path: "${path}". Path cannot contain '..', '?'
- Factory linked work item URL is invalid.
- If the attachment is not an image, it must specify a content
- If the attachment is not an image or text, it must specify a
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/71b48ed702714c44.
Report an issue: GitHub.