can1357/oh-my-pi · error · Error
Host URI scheme contains invalid characters: ${raw.scheme}
Error message
Host URI scheme contains invalid characters: ${raw.scheme} What it means
setSchemes enforces the URI scheme grammar /^[a-z][a-z0-9+.-]*$/ (after trim+lowercase). A scheme that starts with a digit, contains underscores, spaces, or other illegal characters is rejected with this error so host URIs remain parseable.
Source
Thrown at packages/coding-agent/src/modes/rpc/host-uris.ts:98
getSchemes(): string[] {
return Array.from(this.#definitions.keys());
}
/**
* 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()) {View on GitHub (pinned to 9690622007)
Solutions
- Rename the scheme to match [a-z][a-z0-9+.-]* — letters/digits/plus/dot/hyphen, starting with a letter (e.g. my-scheme)
- Normalize identifiers before registration: lowercase and replace invalid chars (underscore → hyphen)
- Validate schemes with the regex client-side before calling setSchemes to give a friendlier error
Example fix
// before
setSchemes([{ scheme: "my_scheme" }]);
// after
const scheme = rawIdentifier.toLowerCase().replace(/[^a-z0-9+.-]/g, "-").replace(/^[^a-z]/, "a$&");
setSchemes([{ scheme }]); Defensive patterns
Strategy: validation
Validate before calling
const SCHEME_RE = /^[a-z][a-z0-9+.-]*$/;
if (!SCHEME_RE.test(scheme.trim().toLowerCase())) throw new Error(`Invalid scheme: ${scheme}`); Type guard
function isWellFormedScheme(s: string): boolean {
return /^[a-z][a-z0-9+.-]*$/.test(s.trim().toLowerCase());
} Try / catch
try {
hostUris.setSchemes(defs);
} catch (err) {
if (err.message.startsWith("Host URI scheme contains invalid characters")) {
logger.warn("Fixing scheme names and retrying", { raw: defs.map(d => d.scheme) });
hostUris.setSchemes(defs.map(sanitizeScheme));
} else throw err;
} Prevention
- Normalize identifiers to lowercase and replace invalid chars before registering
- Use hyphens, never underscores or spaces, in scheme names
- Start scheme names with a letter
- Validate against the scheme regex in config validation
When it happens
Trigger: Calling setSchemes with a scheme like "my_scheme", "1ftp", "my host", or any value that fails the scheme regex — even if it is a non-empty string.
Common situations: Users writing snake_case scheme names in config; copy-pasted schemes with spaces or uppercase+symbols; schemes generated from file names that contain invalid characters.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Host URI scheme must be a non-empty string
- Host URI scheme is reserved by OMP: ${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/2be3eb2964725019.
Report an issue: GitHub.