can1357/oh-my-pi · error
Discord attachment URL is invalid
Error message
Discord attachment URL is invalid
What it means
The Discord uploader extracts an attachment URL from a message payload and validates it before use. If the URL cannot be parsed by the URL constructor or does not use the https: protocol, this error is thrown. It guards against malformed or insecure attachment links returned by Discord.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-discord.ts:66
function webhookEndpoint(webhook: DiscordWebhook, suffix?: string): URL {
const base = `${DISCORD_API_ORIGIN}/api/v10/webhooks/${encodeURIComponent(webhook.id)}/${encodeURIComponent(webhook.token)}`;
return new URL(suffix ? `${base}/${suffix}` : base);
}
function parseMessage(value: unknown): DiscordMessage {
if (!value || typeof value !== "object") throw new Error("Discord returned an invalid message response");
const message = value as Record<string, unknown>;
if (typeof message.id !== "string") throw new Error("Discord response did not include a message ID");
if (!Array.isArray(message.attachments)) throw new Error("Discord response did not include an attachment");
const first = message.attachments[0];
if (!first || typeof first !== "object") throw new Error("Discord response did not include an attachment");
const attachmentUrl = (first as Record<string, unknown>).url;
if (typeof attachmentUrl !== "string") throw new Error("Discord attachment did not include a URL");
try {
const parsed = new URL(attachmentUrl);
if (parsed.protocol !== "https:") throw new Error();
} catch {
throw new Error("Discord attachment URL is invalid");
}
return { id: message.id, attachmentUrl };
}
function attachmentExpiry(url: string, now: number): number {
const signedExpiry = new URL(url).searchParams.get("ex");
if (signedExpiry && /^[0-9a-f]+$/i.test(signedExpiry)) {
const seconds = Number.parseInt(signedExpiry, 16);
const expiresAt = seconds * 1_000;
if (Number.isSafeInteger(expiresAt) && expiresAt > 0) return expiresAt;
}
return now + FALLBACK_LIFETIME_MS;
}
/** Create the built-in Discord webhook uploader, or `null` for another destination. */
export function createDiscordUploader(
destination: BlobDestinationId,
config: DestinationRuntimeConfig,View on GitHub (pinned to 9690622007)
Solutions
- Log the attachment object and confirm `url` is present and a string before calling the uploader
- Ensure the attachment URL is absolute and starts with https:// (Discord CDN URLs normally do)
- If reconstructing payloads, copy `attachment.url` verbatim from the Discord API response instead of building it manually
- Catch this error and fall back to another uploader or surface the message payload for debugging
Example fix
// before
const attachmentUrl = attachment.url ?? `/files/${attachment.id}`;
// after
const attachmentUrl = attachment.url;
if (!attachmentUrl || !attachmentUrl.startsWith("https://")) {
throw new Error(`attachment ${attachment.id} has no https URL`);
} Defensive patterns
Strategy: validation
Validate before calling
function hasHttpsUrl(attachment) {
return typeof attachment?.url === "string" && URL.canParse(attachment.url) && new URL(attachment.url).protocol === "https:";
}
if (!hasHttpsUrl(message.attachments[0])) throw new Error("attachment has no valid https URL"); Type guard
function isDiscordAttachment(value) {
return typeof value === "object" && value !== null && typeof value.url === "string" && value.url.startsWith("https://");
} Try / catch
try {
await broker.publish(request);
} catch (err) {
if (err.message === "Discord attachment URL is invalid") {
logger.warn("Discord attachment unusable", { attachment: firstAttachment });
return null; // or fall back to another broker
}
throw err;
} Prevention
- Copy attachment.url verbatim from Discord API responses; never synthesize it
- Assert https:// scheme on attachment URLs before upload
- Keep Discord API payload shapes in sync with the library's expectations
- Log the raw attachment object when this error fires for debugging
When it happens
Trigger: The first attachment in the message has no `url` string field; the value is not a valid absolute URL (e.g. relative path or garbage); or the URL parses but uses a protocol other than https (http:, cdn:, data:).
Common situations: Consuming Discord message objects from a custom or mocked payload that omits attachment.url; proxy responses rewriting attachment URLs to http; hand-built test fixtures with relative paths; Discord API version changes altering the attachment shape.
Related errors
- Discord webhook credential is not a valid URL
- Discord webhook credential must use HTTPS
- Discord webhook credential does not contain a webhook ID and
- ${destination} returned an invalid image URL
- Invalid memory glob URL: ${input}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/98e41d062b0f2a4d.
Report an issue: GitHub.