{"record":{"id":"d8b849835b499101","repo":"can1357/oh-my-pi","slug":"unknown-protocol-scheme-supported-availa","errorCode":null,"errorMessage":"Unknown protocol: ${scheme}://\nSupported: ${available || \"none\"}","messagePattern":"Unknown protocol: (.+?)://\nSupported: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/internal-urls/router.ts","lineNumber":132,"sourceCode":"\t\tif (!handler?.complete) return null;\n\t\treturn handler.complete(query, context);\n\t}\n\n\t#isMcpResourceScheme(scheme: string): boolean {\n\t\treturn ![\"file\", \"http\", \"https\"].includes(scheme) && this.#handlers.has(\"mcp\");\n\t}\n\n\t#route(input: string, allowMcpResource = false): { parsed: InternalUrl; handler: ProtocolHandler } {\n\t\tconst parsed = parseInternalUrl(input);\n\t\tconst scheme = parsed.protocol.replace(/:$/, \"\").toLowerCase();\n\t\tconst handler =\n\t\t\tthis.#handlers.get(scheme) ??\n\t\t\t(allowMcpResource && this.#isMcpResourceScheme(scheme) ? this.#handlers.get(\"mcp\") : undefined);\n\t\tif (!handler) {\n\t\t\tconst available = Array.from(this.#handlers.keys())\n\t\t\t\t.map(candidate => `${candidate}://`)\n\t\t\t\t.join(\", \");\n\t\t\tthrow new Error(`Unknown protocol: ${scheme}://\\nSupported: ${available || \"none\"}`);\n\t\t}\n\t\treturn { parsed, handler };\n\t}\n\n\t/** Resolve an internal URL through its registered protocol handler. */\n\tasync resolve(input: string, context?: ResolveContext): Promise<InternalResource> {\n\t\tconst { parsed, handler } = this.#route(input, true);\n\t\tconst resource = await handler.resolve(parsed, context);\n\t\treturn { ...resource, immutable: resource.immutable ?? handler.immutable };\n\t}\n\n\t/** Write an internal URL through its registered protocol handler. */\n\tasync write(input: string, content: string, context?: WriteContext): Promise<void> {\n\t\tconst { parsed, handler } = this.#route(input);\n\t\tif (!handler.write) {\n\t\t\tconst scheme = parsed.protocol.replace(/:$/, \"\").toLowerCase();\n\t\t\tthrow new Error(`${scheme}:// URLs are read-only for write; use the protocol-specific tool for mutations.`);\n\t\t}","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/internal-urls/router.ts#L114-L150","documentation":"The internal URL router dispatches by scheme to registered protocol handlers. #route throws this when the scheme of the URL has no registered handler (and is not an accepted mcp-resource scheme), listing all currently supported schemes in the message.","triggerScenarios":"Resolving or writing a URL like file://..., https://..., or a typo'd scheme (e.g. 'omps://') through the internal-URL router, which only handles registered internal schemes.","commonSituations":"Confusing internal URLs with regular web/file URLs; typos in the scheme; calling the router with an MCP scheme while MCP resource support is disabled (allowMcpResource false).","solutions":["Use a supported scheme from the error's 'Supported:' list (e.g. omp://, memory://, rule://).","Fix typos in the scheme name.","If you intended an mcp:// resource URL, route it where MCP resources are allowed (allowMcpResource enabled).","Handle file/web URLs with the normal file-read or HTTP tooling, not the internal router."],"exampleFix":"// before\nawait router.resolve('https://example.com');\n// after: check scheme first\nconst scheme = new URL(input).protocol.replace(/:$/, '').toLowerCase();\nif (!['omp', 'memory', 'rule'].includes(scheme)) throw new Error(`use a native tool for ${scheme}://`);\nawait router.resolve(input);","handlingStrategy":"validation","validationCode":"const supported = ['omp', 'memory', 'rule']; // keep in sync with registered handlers\nconst scheme = input.split('://')[0]?.toLowerCase();\nif (!scheme || !supported.includes(scheme)) throw new Error(`unsupported internal scheme: ${scheme ?? input}`);","typeGuard":"const isInternalUrl = (s: string): boolean =>\n  ['omp', 'memory', 'rule'].includes(s.split('://')[0]?.toLowerCase() ?? '');","tryCatchPattern":"try {\n  return await router.resolve(input);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unknown protocol:')) {\n    logger.warn('unhandled internal URL scheme', { input });\n    return null;\n  }\n  throw err;\n}","preventionTips":["Check the 'Supported:' list in the error to learn which schemes the router handles.","Route web/file URLs to the appropriate tool instead of the internal router.","Fix scheme typos; compare against the registry rather than hardcoding."],"tags":["internal-url","routing","unsupported-scheme"],"backgroundTag":"unsupported-scheme","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}