can1357/oh-my-pi · error · LegacyDestinationError

the configured endpoint is not a valid URL

Error message

the configured endpoint is not a valid URL

What it means

This LegacyDestinationError is thrown when the user-configured `endpoint` option for a legacy blob destination (puush, mediafire, localhostr, lambda, lobfile, transfer-sh, sendspace, etc.) cannot be parsed by the URL constructor. The library requires a custom replacement endpoint because the original public services are defunct, and it validates the value with `new URL(raw)` before any network I/O. It wraps the underlying parse error as `cause`.

Source

Thrown at packages/coding-agent/src/blob-broker/uploaders-legacy.ts:70

	readonly extraInfo: string;
}

function failure(destination: BlobDestinationId, error: unknown): Error {
	if (error instanceof DestinationUnavailableError || error instanceof LegacyDestinationError) return error;
	const message = error instanceof Error ? error.message : String(error);
	return new LegacyDestinationError(destination, message, error);
}

function configuredEndpoint(destination: BlobDestinationId, config: DestinationRuntimeConfig): URL {
	const raw = optionString(config, "endpoint")?.trim();
	if (!raw) {
		throw new DestinationUnavailableError(destination, "a user-supplied replacement endpoint is required");
	}
	let endpoint: URL;
	try {
		endpoint = new URL(raw);
	} catch (error) {
		throw new LegacyDestinationError(destination, "the configured endpoint is not a valid URL", error);
	}
	if (endpoint.protocol !== "https:" && endpoint.protocol !== "http:") {
		throw new LegacyDestinationError(destination, "the configured endpoint must use HTTP or HTTPS");
	}
	const hostname = endpoint.hostname.toLowerCase();
	const blocked = BLOCKED_CUSTOM_HOSTS[destination];
	if (blocked) {
		for (const domain of blocked) {
			if (hostname === domain || hostname.endsWith(`.${domain}`)) {
				throw new DestinationUnavailableError(destination, "the defunct public endpoint cannot be used");
			}
		}
	}
	return endpoint;
}

function sendSpaceEndpoint(config: DestinationRuntimeConfig): URL {
	const endpoint = configuredEndpoint("sendspace", config);

View on GitHub (pinned to 9690622007)

Solutions

  1. Prefix the endpoint with an explicit scheme, e.g. change 'files.example.com/upload' to 'https://files.example.com/upload'
  2. Trim quotes, whitespace, and template remnants from the configured endpoint value
  3. Validate the string with `new URL(value)` before saving it to configuration
  4. Check the wrapped `cause` property of the error for the exact WHATWG URL parse failure

Example fix

// before
endpoint: files.example.com/upload
// after
endpoint: https://files.example.com/upload
Defensive patterns

Strategy: validation

Validate before calling

function isValidHttpUrl(value) {
  try {
    const u = new URL(String(value).trim());
    return u.protocol === "https:" || u.protocol === "http:";
  } catch {
    return false;
  }
}
if (!isValidHttpUrl(config.endpoint)) throw new Error("endpoint must be an absolute http(s) URL");

Type guard

function isHttpUrl(value: unknown): value is URL {
  try {
    const u = new URL(String(value));
    return u.protocol === "https:" || u.protocol === "http:";
  } catch {
    return false;
  }
}

Try / catch

try {
  await uploader.upload(request);
} catch (err) {
  if (err instanceof Error && err.message.includes("not a valid URL")) {
    // fix config.endpoint: add scheme, trim junk
  } else throw err;
}

Prevention

When it happens

Trigger: Calling an uploader that resolves its endpoint via configuredEndpoint() (e.g. createLegacyUploader -> endpoint) with config.endpoint set to a string that fails `new URL()`: a bare hostname like 'example.com/upload' without a scheme, an empty-after-trim value is handled separately, typos like 'https//...', or values with spaces/invalid characters.

Common situations: Users copy a replacement endpoint from documentation and omit the `https://` scheme; environment variables or YAML config with trailing whitespace/quotes left in the value; template expansion producing 'undefined' or placeholder text in the endpoint string.

Related errors


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