can1357/oh-my-pi · error

Discord webhook credential is not a valid URL

Error message

Discord webhook credential is not a valid URL

What it means

The Discord uploader parses the configured `webhookUrl` credential with the URL constructor before using it. If the credential string cannot be parsed as a URL at all (new URL throws), this error is thrown so the misconfiguration is reported at destination setup time rather than as a confusing fetch failure.

Source

Thrown at packages/coding-agent/src/blob-broker/uploaders-discord.ts:32

const DISCORD_API_ORIGIN = "https://discord.com";
const FALLBACK_LIFETIME_MS = 24 * 60 * 60 * 1_000;

interface DiscordWebhook {
	id: string;
	token: string;
}

interface DiscordMessage {
	id: string;
	attachmentUrl: string;
}

function parseWebhook(value: string): DiscordWebhook {
	let url: URL;
	try {
		url = new URL(value);
	} catch {
		throw new Error("Discord webhook credential is not a valid URL");
	}

	if (url.protocol !== "https:") {
		throw new Error("Discord webhook credential must use HTTPS");
	}
	const segments = url.pathname.split("/").filter(Boolean);
	const webhooksIndex = segments.indexOf("webhooks");
	const id = webhooksIndex >= 0 ? segments[webhooksIndex + 1] : undefined;
	const token = webhooksIndex >= 0 ? segments[webhooksIndex + 2] : undefined;
	if (!id || !token || !/^\d+$/.test(id)) {
		throw new Error("Discord webhook credential does not contain a webhook ID and token");
	}
	return { id, token };
}

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);

View on GitHub (pinned to 9690622007)

Solutions

  1. Copy the webhook URL directly from Discord (Server Settings → Integrations → Webhooks → Copy Webhook URL) including the https:// prefix
  2. Trim whitespace and remove surrounding quotes from the credential value
  3. Confirm the config source (env var, settings file) actually resolves to a non-empty string
  4. Validate the URL with `new URL(value)` locally before saving it to config

Example fix

// before
webhookUrl = discord.com/api/webhooks/123/abc "
// after
webhookUrl = https://discord.com/api/webhooks/123/abc
Defensive patterns

Strategy: validation

Validate before calling

function validateWebhookUrl(value) {
  let url;
  try {
    url = new URL(value.trim());
  } catch {
    throw new Error('webhookUrl is not a valid URL');
  }
  return url;
}
validateWebhookUrl(process.env.DISCORD_WEBHOOK_URL);

Try / catch

try {
  await publishToDiscord(blob);
} catch (err) {
  if (err.message.includes('not a valid URL')) {
    logger.error('DISCORD_WEBHOOK_URL is malformed — copy the full https:// URL from Discord');
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: The `webhookUrl` option in the discord destination config is empty, contains only whitespace, is missing its scheme (e.g. `discord.com/api/webhooks/...`), or contains characters that make it unparseable by `new URL()` (unencoded spaces, stray quotes from copy-paste).

Common situations: Copy-pasting a webhook URL with trailing whitespace or quotes; storing the webhook in an env var that was never set so an empty string is passed; hand-typing the URL and omitting `https://`; shell quoting mangling the value in a config file.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f5aaff115d83bed5. Report an issue: GitHub.