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
- Log the offending value to see what the host returned for the URL field
- Prepend the host base URL if the API now returns relative paths
- Update the uploader if the URL moved to a different response field
- 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
- Assert absolute http(s) URLs when integrating a new host
- Handle hosts that return relative paths by prefixing their base URL
- Sanitize host responses rather than trusting the URL field blindly
- Keep mocks/fixtures realistic (absolute https URLs) in tests
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
- Discord attachment URL is invalid
- ${destination} returned an invalid response
- ${destination} response did not include ${key}
- Invalid memory glob URL: ${input}
- Invalid skill:// URL: ${url}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/695c1539121bbf45.
Report an issue: GitHub.