{"record":{"id":"be92cabde4b06510","repo":"can1357/oh-my-pi","slug":"cannot-internalurlaction-a-remote-ssh-path","errorCode":null,"errorMessage":"Cannot ${internalUrlAction} a remote ssh:// path (no local file): ${rawPath}. Use \\`read ${rawPath}\\` to view it, or use \\`grep\\` on a specific remote file.","messagePattern":"Cannot (.+?) a remote ssh:// path \\(no local file\\): (.+?)\\. Use \\\\`read (.+?)\\\\` to view it, or use \\\\`grep\\\\` on a specific remote file\\.","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/path-utils.ts","lineNumber":1547,"sourceCode":"\t\t\t\tresolvedPathInputs.push(resolved.sourcePath);\n\t\t\t\tif (opts.trackImmutableSources && resolved.immutable) {\n\t\t\t\t\timmutableSourcePaths.add(path.resolve(resolved.sourcePath));\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Resolver missing or declined (e.g. ftp/ws/wss): fail explicitly\n\t\t\t// instead of letting the local-path fallthrough surface a confusing\n\t\t\t// \"Path not found\" for a URL-shaped input.\n\t\t\tthrow new ToolError(\n\t\t\t\t`Cannot ${internalUrlAction} external URL: ${rawPath}. Use \\`read\\` to fetch web content, then search the returned text.`,\n\t\t\t);\n\t\t}\n\t\tif (!internalRouter.canHandle(rawPath)) {\n\t\t\tresolvedPathInputs.push(rawPath);\n\t\t\tcontinue;\n\t\t}\n\t\tif (isSshUrl(rawPath)) {\n\t\t\tthrow new ToolError(\n\t\t\t\t`Cannot ${internalUrlAction} a remote ssh:// path (no local file): ${rawPath}. Use \\`read ${rawPath}\\` to view it, or use \\`grep\\` on a specific remote file.`,\n\t\t\t);\n\t\t}\n\t\tif (hasGlobPathChars(rawPath)) {\n\t\t\tthrow new ToolError(`Glob patterns are not supported for internal URLs: ${rawPath}`);\n\t\t}\n\t\tconst resource = await internalRouter.resolve(rawPath, {\n\t\t\tcwd,\n\t\t\tsettings: opts.settings,\n\t\t\tsignal: opts.signal,\n\t\t\tsessionFile: opts.sessionFile,\n\t\t\tlocalProtocolOptions: opts.localProtocolOptions,\n\t\t\tskills: opts.skills,\n\t\t\t// Tool-scope resolution only needs `sourcePath`; skip content\n\t\t\t// materialization so large artifacts (or any handler that separates\n\t\t\t// path from content) stay searchable without OOM risk.\n\t\t\tpathOnly: true,\n\t\t});","sourceCodeStart":1529,"sourceCodeEnd":1565,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/path-utils.ts#L1529-L1565","documentation":"ssh:// URLs are recognized by the internal URL router but represent remote files with no local backing, so search-scope resolution rejects them explicitly. The message directs you to `read` (which can render remote content) or grep on a specific remote file path.","triggerScenarios":"Passing a scope entry like `ssh://host/repo/src` to search/ast_grep/ast_edit via resolveToolSearchScope where isSshUrl(rawPath) is true — the router canHandle it but there is no local file to search.","commonSituations":"Agent or user points a bulk search at a remote SSH path expecting it to behave like a local directory; mixing remote repo references into an otherwise local path list.","solutions":["Use `read ssh://host/repo/src` to view the remote content instead of searching it.","Run grep against a specific remote file path rather than a directory-level search scope.","Clone or mount the remote repository locally, then search the local path.","If the ssh URL maps to a locally checked-out workspace, reference the local path instead."],"exampleFix":"// before\nsearch({ pattern: \"FIXME\", paths: [\"ssh://dev@box/srv/app\"] })\n// after\nawait read({ path: \"ssh://dev@box/srv/app/src/main.ts\" });\n// or: git clone ssh://dev@box/srv/app && search({ paths: [\"./app\"] })","handlingStrategy":"validation","validationCode":"if (p.startsWith(\"ssh://\")) {\n  throw new Error(\"ssh:// paths cannot back a search scope; use read or clone locally\");\n}","typeGuard":"const isSshPath = (p) => p.startsWith(\"ssh://\");","tryCatchPattern":"try { scope = await resolveToolSearchScope(opts); }\ncatch (e) {\n  if (e.message.includes(\"remote ssh:// path\")) {\n    return read({ path: p }); // degrade to viewing the remote resource\n  }\n  throw e;\n}","preventionTips":["Treat ssh:// as read-only renderable content, never a search scope.","Clone or mount remote repos before bulk search.","Filter remote schemes out of path lists intended for local search."],"tags":["ssh","remote","search","unsupported-operation"],"backgroundTag":"remote-path-not-local","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}