{"record":{"id":"62e860640a56e021","repo":"can1357/oh-my-pi","slug":"scheme-url-resolved-without-a-filesystem-pat","errorCode":null,"errorMessage":"${scheme}:// URL resolved without a filesystem path and cannot be used in bash: ${url}","messagePattern":"(.+?):// URL resolved without a filesystem path and cannot be used in bash: (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/bash-skill-urls.ts","lineNumber":311,"sourceCode":"\t}\n\n\tif (!internalRouter?.canHandle(url)) {\n\t\tthrow new ToolError(\n\t\t\t`Cannot resolve ${scheme}:// URL in bash command: ${url}\\n` +\n\t\t\t\t\"Internal URL router is unavailable for this protocol in the current session.\",\n\t\t);\n\t}\n\n\tlet resource: InternalResource;\n\ttry {\n\t\tresource = await internalRouter.resolve(url, { cwd, pathOnly: true, sessionFile });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tthrow new ToolError(`Failed to resolve ${scheme}:// URL in bash command: ${url}\\n${message}`);\n\t}\n\n\tif (!resource.sourcePath) {\n\t\tthrow new ToolError(`${scheme}:// URL resolved without a filesystem path and cannot be used in bash: ${url}`);\n\t}\n\n\treturn path.resolve(resource.sourcePath);\n}\n\n/**\n * Expand all skill:// URIs in a bash command string.\n * Returns the command with URIs replaced by shell-escaped absolute paths.\n * Throws ToolError if any URI cannot be resolved.\n */\nexport function expandSkillUrls(command: string, skills: readonly Skill[]): string {\n\tif (skills.length === 0 || !command.includes(\"skill://\")) {\n\t\treturn command;\n\t}\n\n\treturn command.replace(SKILL_URL_PATTERN, token => {\n\t\tconst url = unquoteToken(token);\n\t\tconst resolvedPath = resolveSkillUrlToPath(url, skills);","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/bash-skill-urls.ts#L293-L329","documentation":"The router resolved the URL successfully but returned an InternalResource without a sourcePath. Since bash commands can only operate on real filesystem paths, the tool refuses to substitute anything and throws this ToolError, naming the scheme and URL.","triggerScenarios":"A handler returns an in-memory/virtual resource (e.g. generated content, a stream, a URI with no filesystem backing) for a URL used inside a bash command; a custom plugin handler implements resolve() but doesn't populate resource.sourcePath when pathOnly: true is requested.","commonSituations":"Plugin schemes backed by databases, remote fetches, or virtual documents being referenced in bash commands; a handler bug where sourcePath is only set on some code paths.","solutions":["Materialize the resource to a real file first (e.g. write it via a tool that supports it) and reference that path in bash.","Fix or update the plugin handler so it returns a sourcePath for pathOnly requests.","Use a scheme with filesystem backing (skill://, local://, attachment://) in bash commands.","If you control the handler, ensure InternalResource.sourcePath is always populated for bash-capable resources."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await expandInternalUrls(cmd, ctx); } catch (e) { if (e instanceof ToolError && /resolved without a filesystem path/.test(e.message)) materializeResourceToFile(e); else throw e; }","preventionTips":["Use bash only for schemes with filesystem backing; handle virtual resources with tools that read them directly.","If you write handlers, always populate InternalResource.sourcePath for pathOnly resolution.","Materialize in-memory resources to temp files before shell commands need them."],"tags":["bash","url-router","virtual-resource"],"backgroundTag":"resource-has-no-filesystem-path","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}