can1357/oh-my-pi · error · Error

Host URI scheme is reserved by OMP: ${scheme}://

Error message

Host URI scheme is reserved by OMP: ${scheme}://

What it means

A set of scheme names reserved by OMP (RESERVED_HOST_URI_SCHEMES) cannot be registered by external/RPC callers, to prevent collisions with built-in host URI handlers. Registering such a scheme throws immediately with the colliding name.

Source

Thrown at packages/coding-agent/src/modes/rpc/host-uris.ts:101

	}

	/**
	 * Replace the registered set of host URI schemes. Previously registered
	 * schemes that no longer appear in the new set are unregistered from the
	 * router; surviving and new schemes get fresh handler instances.
	 */
	setSchemes(schemes: RpcHostUriSchemeDefinition[]): string[] {
		const normalized = new Map<string, RpcHostUriSchemeDefinition>();
		for (const raw of schemes) {
			const scheme = typeof raw?.scheme === "string" ? raw.scheme.trim().toLowerCase() : "";
			if (!scheme) {
				throw new Error("Host URI scheme must be a non-empty string");
			}
			if (!/^[a-z][a-z0-9+.-]*$/.test(scheme)) {
				throw new Error(`Host URI scheme contains invalid characters: ${raw.scheme}`);
			}
			if (RESERVED_HOST_URI_SCHEMES.has(scheme)) {
				throw new Error(`Host URI scheme is reserved by OMP: ${scheme}://`);
			}
			normalized.set(scheme, {
				scheme,
				description: typeof raw.description === "string" ? raw.description : undefined,
				writable: raw.writable === true,
				immutable: raw.immutable === true,
			});
		}

		for (const previous of this.#definitions.keys()) {
			if (!normalized.has(previous)) {
				this.#router.unregister(previous);
			}
		}
		for (const definition of normalized.values()) {
			this.#router.register(new RpcHostUriProtocolHandler(definition, this));
		}
		this.#definitions = normalized;

View on GitHub (pinned to 9690622007)

Solutions

  1. Rename the scheme to something namespaced and unreserved (e.g. myplugin-docs instead of the reserved name)
  2. Check the reserved list in host-uris.ts and pick a non-colliding name before registering
  3. If you need built-in-scheme behavior, use the built-in handler rather than registering a duplicate

Example fix

// before
setSchemes([{ scheme: "file", description: "custom files" }]);
// after
setSchemes([{ scheme: "myapp-file", description: "custom files" }]);
Defensive patterns

Strategy: validation

Validate before calling

import { RESERVED_HOST_URI_SCHEMES } from "./host-uris"; // or inline the known reserved set
if (RESERVED_HOST_URI_SCHEMES.has(scheme.trim().toLowerCase())) throw new Error(`Scheme ${scheme} is reserved`);

Type guard

function isRegisterableScheme(s: string, reserved: Set<string>): boolean {
  const norm = s.trim().toLowerCase();
  return norm !== "" && !reserved.has(norm);
}

Try / catch

try {
  hostUris.setSchemes(defs);
} catch (err) {
  if (err.message.startsWith("Host URI scheme is reserved")) {
    logger.warn("Renaming reserved scheme", { raw: err.message });
    hostUris.setSchemes(defs.map(d => RESERVED.has(d.scheme) ? { ...d, scheme: nsPrefix(d.scheme) } : d));
  } else throw err;
}

Prevention

When it happens

Trigger: Calling setSchemes with a scheme whose lowercased name is present in RESERVED_HOST_URI_SCHEMES (built-in OMP schemes) — e.g. attempting to override a scheme like "file" or another internal scheme.

Common situations: A plugin/RPC client trying to shadow a built-in host URI scheme; a generic config reusing a common word (e.g. "app", "file") that happens to be reserved; migration from a setup where the scheme was previously allowed.

Related errors


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