can1357/oh-my-pi · error · Error

error

Error message

error

What it means

formatCollabLink normalizes the relay URL before rendering the shareable link and throws when normalizeRelayOrigin returns an error — an unparseable URL, an unsupported scheme, or ws:// pointing at a non-localhost host. This is the same relay-URL validation as the host-start path, surfaced at link formatting time.

Source

Thrown at packages/coding-agent/src/collab/protocol.ts:197

/**
 * Render the shareable link. Compact forms: the default relay collapses to
 * `<roomId>.<key>`, other wss relays drop the scheme (`host[:port]/r/…`);
 * only localhost ws:// links keep their full URL so parsing cannot
 * mis-infer wss.
 *
 * The room secret is dot-joined (`<roomId>.<key>`) rather than `#`-joined:
 * RFC 3986 forbids a raw `#` inside a fragment, so strict URL stacks (macOS
 * Foundation behind terminal click-to-open) percent-encode a second `#` to
 * `%23` and break the link. Parsers still accept the legacy `#` form and the
 * mangled `%23` form.
 *
 * Full links append the write token to the key
 * (`base64url(key ∥ writeToken)`); read-only (view) links carry the bare
 * 32-byte key, which is also the pre-token link format.
 */
export function formatCollabLink(relayUrl: string, roomId: string, key: Uint8Array, writeToken?: Uint8Array): string {
	const normalized = normalizeRelayOrigin(relayUrl);
	if ("error" in normalized) throw new Error(normalized.error);
	const secret = writeToken ? Buffer.concat([key, writeToken]) : Buffer.from(key);
	const keyText = secret.toString("base64url");
	if (normalized.origin === DEFAULT_RELAY_URL) return `${roomId}.${keyText}`;
	const compact = normalized.origin.startsWith("wss://")
		? normalized.origin.slice("wss://".length)
		: normalized.origin;
	return `${compact}/r/${roomId}.${keyText}`;
}

function normalizeCollabWebBaseUrl(relayUrl: string, webUrl?: string): string {
	const explicitWebUrl = webUrl?.trim();
	if (!explicitWebUrl) {
		const normalized = normalizeRelayOrigin(relayUrl);
		if ("error" in normalized) throw new Error(normalized.error);
		return normalized.origin.startsWith("wss://")
			? `https://${normalized.origin.slice("wss://".length)}`
			: `http://${normalized.origin.slice("ws://".length)}`;
	}

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass a complete ws:// or wss:// URL with hostname (and optional port) as relayUrl.
  2. For remote relays use wss://; reserve ws:// for localhost/127.0.0.1/::1 only.
  3. Validate with new URL(relayUrl) and check url.protocol in ["ws:","wss:","http:","https:"] before calling.
  4. Use the DEFAULT_RELAY_URL (empty relayUrl handling in the caller) if self-hosting is not intended.

Example fix

// before
formatCollabLink("ws://relay.example.com", roomId, key); // plain ws off localhost
// after
formatCollabLink("wss://relay.example.com", roomId, key);
Defensive patterns

Strategy: validation

Validate before calling

const u = new URL(relayUrl); // throws if invalid
const schemeOk = ["ws:", "wss:", "http:", "https:"].includes(u.protocol);
const localOk = u.protocol !== "ws:" || ["localhost", "127.0.0.1", "::1"].includes(u.hostname);
if (!schemeOk || !localOk) throw new Error(`unsupported relayUrl: ${relayUrl}`);
formatCollabLink(relayUrl, roomId, key, token);

Try / catch

try {
  const link = formatCollabLink(relayUrl, roomId, key, token);
} catch (err) {
  ui.showError(`Cannot format link: ${(err as Error).message}`);
}

Prevention

When it happens

Trigger: Calling formatCollabLink(relayUrl, roomId, key[, writeToken]) with relayUrl that is not a valid absolute URL, has a scheme other than ws/wss/http/https, or uses ws:// with a non-local hostname. Also reachable via formatCollabWebLink, which calls it after building the web base URL.

Common situations: Environment/config variable for the relay is empty or a bare hostname; a self-hosted relay configured as 'http://relay:8080' works, but 'ftp://relay' or a typo ('wss//relay') fails; ws:// used for a remote relay in a dev environment with a real hostname.

Related errors


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