can1357/oh-my-pi · error

${destination} returned an invalid image URL

Error message

${destination} returned an invalid image URL

What it means

directUrl parses a value returned by the image host into a URL object; if the string is not a syntactically valid absolute URL, this error is thrown. This is the parse-failure branch of URL validation for destination-issued image links.

Source

Thrown at packages/coding-agent/src/blob-broker/uploaders-image-hosts.ts:68

	destination: BlobDestinationId,
): Record<string, unknown> {
	return responseRecord(record[key], destination);
}

function requiredString(record: Record<string, unknown>, key: string, destination: BlobDestinationId): string {
	const value = record[key];
	if (typeof value !== "string" || value.length === 0) {
		throw new Error(`${destination} response did not include ${key}`);
	}
	return value;
}

function directUrl(value: string, destination: BlobDestinationId): string {
	let url: URL;
	try {
		url = new URL(value);
	} catch {
		throw new Error(`${destination} returned an invalid image URL`);
	}
	if (url.protocol !== "https:" && url.protocol !== "http:") {
		throw new Error(`${destination} returned an invalid image URL`);
	}
	return url.href;
}

function createImgurUploader(config: DestinationRuntimeConfig): BlobUploader {
	const accessToken = credentialString(config, "accessToken");
	const authorization = accessToken ? `Bearer ${accessToken}` : `Client-ID ${requireCredential(config, "clientId")}`;
	const album = optionString(config, "album");

	return {
		destination: "imgur",
		async upload(request) {
			const fields: Record<string, string> = {};
			if (album) fields.album = album;
			const response = await fetchFor(config)(IMGUR_UPLOAD_URL, {

View on GitHub (pinned to 9690622007)

Solutions

  1. Log the offending value to see what the host returned for the URL field
  2. Prepend the host base URL if the API now returns relative paths
  3. Update the uploader if the URL moved to a different response field
  4. Validate URLs with a guard before passing them into the broker

Example fix

// before
const url = result.path; // "/images/abc.png"
// after
const url = new URL(result.path, "https://host.example").href;
Defensive patterns

Strategy: validation

Validate before calling

function isHttpUrl(value) {
  try {
    const u = new URL(value);
    return u.protocol === "https:" || u.protocol === "http:";
  } catch { return false; }
}
if (!isHttpUrl(hostResponse.url)) throw new Error("host returned a non-URL value");

Type guard

function isUrlString(value) {
  return typeof value === "string" && URL.canParse(value);
}

Try / catch

try {
  const pub = await broker.publish(request);
} catch (err) {
  if (err.message.endsWith("returned an invalid image URL")) {
    logger.warn("host issued unusable image URL", { raw: hostResponse.url });
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: The host returns a relative path, an empty string, or arbitrary text where a URL is expected, and new URL(value) throws.

Common situations: Host returns a path like /images/123 instead of an absolute URL; mocked responses with placeholder strings; schema changes moving the real URL elsewhere so a non-URL field is read.

Related errors


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