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
- Rename the scheme to something namespaced and unreserved (e.g. myplugin-docs instead of the reserved name)
- Check the reserved list in host-uris.ts and pick a non-colliding name before registering
- 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
- Namespace custom schemes with a plugin/app prefix to avoid built-in collisions
- Check the reserved scheme list before choosing a name
- Never attempt to override built-in host URI handlers
- Keep a config lint that flags reserved scheme names
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
- Host URI scheme must be a non-empty string
- Host URI scheme contains invalid characters: ${raw.scheme}
- Unsupported language '{value}'. Supported: {}
- Unable to infer language from file extension: {}. Specify `l
- Invalid pattern: {err}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b8fa0d26263cd418.
Report an issue: GitHub.