can1357/oh-my-pi · error · DestinationUnavailableError

the defunct public endpoint cannot be used

Error message

the defunct public endpoint cannot be used

What it means

This DestinationUnavailableError is thrown when the configured custom endpoint's hostname matches a blocked domain (or subdomain of it) for the destination — the defunct public service hosts listed in BLOCKED_CUSTOM_HOSTS (e.g. puush.me, mediafire.com, transfer.sh). The library blocks these because the services are shut down and the endpoint would never work, so it fails fast with a clear reason instead of a confusing network error.

Source

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

	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);
	if (endpoint.hostname.toLowerCase() === SENDSPACE_DEFAULT_HOST) {
		throw new DestinationUnavailableError("sendspace", "the deprecated public discovery endpoint cannot be used");
	}
	return endpoint;
}

function httpUrl(destination: BlobDestinationId, raw: string, base?: URL): string {
	let url: URL;
	try {
		url = base ? new URL(raw, base) : new URL(raw);

View on GitHub (pinned to 9690622007)

Solutions

  1. Point the endpoint at a working self-hosted or third-party replacement host, not the original defunct domain
  2. Remove any subdomain of the blocked domain (e.g. api.puush.me is also blocked)
  3. Consult the destination list in BLOCKED_CUSTOM_HOSTS (uploaders-legacy.ts) to see which hosts are disallowed
  4. If a mirror of the service exists, use its current non-blocked hostname

Example fix

// before
endpoint: https://puush.me/api/up
// after
endpoint: https://my-own-host.example.com/api/up
Defensive patterns

Strategy: validation

Validate before calling

const blocked = { puush: ["puush.me"], "transfer-sh": ["transfer.sh"] };
const host = new URL(config.endpoint).hostname.toLowerCase();
for (const [dest, domains] of Object.entries(blocked)) {
  if (domains.some(d => host === d || host.endsWith("." + d))) {
    throw new Error(`${dest}: endpoint ${host} is a defunct public host; supply a replacement`);
  }
}

Try / catch

try {
  await uploader.upload(request);
} catch (err) {
  if (err instanceof Error && err.message.includes("defunct public endpoint")) {
    // repoint endpoint at a working replacement host
  } else throw err;
}

Prevention

When it happens

Trigger: Configuring a destination with its own defunct public host, exactly or as a subdomain: e.g. puush endpoint 'https://puush.me/api/up', transfer-sh endpoint 'https://transfer.sh/xxx', or 'https://old.mediafire.com/api' — configuredEndpoint() lowercases the hostname and compares equality or `.endsWith('.'+domain)`.

Common situations: Users restore old configuration pointing at the original service after it shut down; documentation or blog posts still referencing the dead public API; assuming a subdomain of the dead host still works.

Related errors


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