can1357/oh-my-pi · error · Error

Destination option endpoint must be an absolute URL

Error message

Destination option endpoint must be an absolute URL

What it means

requiredEndpoint() throws this when the configured endpoint string cannot be parsed by the URL constructor — it is present but not an absolute URL (missing scheme, malformed host, whitespace, etc.).

Source

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

			const getSizesParameters: Record<string, string> = { ...getSizesFields, ...getSizesOAuth };
			for (const key in getSizesParameters) {
				getSizesUrl.searchParams.append(key, getSizesParameters[key]);
			}
			const sizesResponse = await fetchFor(config)(getSizesUrl, { method: "GET" });
			const sizes = await jsonResponse(sizesResponse, "flickr");
			return publication("flickr", request, largestFlickrSource(sizes), { remoteId: photoId });
		},
	};
}

function requiredEndpoint(config: DestinationRuntimeConfig): string {
	const endpoint = optionString(config, "endpoint");
	if (!endpoint) throw new Error("Missing required destination option: endpoint");
	let url: URL;
	try {
		url = new URL(endpoint);
	} catch {
		throw new Error("Destination option endpoint must be an absolute URL");
	}
	if (url.protocol !== "https:" && url.protocol !== "http:") {
		throw new Error("Destination option endpoint must use HTTP or HTTPS");
	}
	return url.href;
}

function createCheveretoUploader(config: DestinationRuntimeConfig): BlobUploader {
	const endpoint = requiredEndpoint(config);
	const apiKey = requireCredential(config, "apiKey");

	return {
		destination: "chevereto",
		async upload(request) {
			const response = await fetchFor(config)(endpoint, {
				method: "POST",
				body: multipartFile(request, "source", { key: apiKey, format: "json" }),
			});

View on GitHub (pinned to 9690622007)

Solutions

  1. Prefix the endpoint with https:// if you wrote a bare hostname
  2. Trim whitespace and remove stray quotes from the endpoint value
  3. Validate the URL in a browser or curl before saving it to config
  4. Use the full absolute URL including scheme, e.g. https://chev.example.com/api/upload

Example fix

// before
"endpoint": "chev.example.com/api/upload"
// after
"endpoint": "https://chev.example.com/api/upload"
Defensive patterns

Strategy: validation

Validate before calling

const ep = config.options?.endpoint;
if (typeof ep === "string" && ep.trim()) {
	try { new URL(ep); } catch { throw new Error(`endpoint '${ep}' is not an absolute URL (add https://)`); }
}

Type guard

function isAbsoluteHttpUrl(value: unknown): value is string {
	if (typeof value !== "string") return false;
	try { const u = new URL(value); return u.protocol === "http:" || u.protocol === "https:"; } catch { return false; }
}

Try / catch

try {
	const href = requiredEndpoint(config);
} catch (err) {
	if (err instanceof Error && err.message.includes("absolute URL")) {
		// hint: prefix with https://
	}
	throw err;
}

Prevention

When it happens

Trigger: Endpoint values like 'chev.example.com' (no scheme), 'localhost:80' (parsed as scheme 'localhost'), 'https://' (empty host), or a value containing spaces/newlines from a pasted config.

Common situations: Users pasting a hostname without 'https://', quotes or whitespace surviving YAML/JSON parsing, or a truncated URL from a bad copy-paste.

Related errors


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