{"record":{"id":"c2aeb0a442c9969d","repo":"can1357/oh-my-pi","slug":"find-cannot-operate-on-a-remote-ssh-path-raw","errorCode":null,"errorMessage":"find cannot operate on a remote ssh:// path: ${rawPattern}. ssh:// has no local file to glob; use `read ${rawPattern}` to list or inspect the remote path.","messagePattern":"find cannot operate on a remote ssh:// path: (.+?)\\. ssh:// has no local file to glob; use `read (.+?)` to list or inspect the remote path\\.","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/glob.ts","lineNumber":214,"sourceCode":"\t\t\tconst rawPatternInputs = this.#customOps\n\t\t\t\t? effectivePaths\n\t\t\t\t: await expandDelimitedPathEntries(effectivePaths, this.session.cwd, { splitter: parseFindPattern });\n\t\t\tconst rawPatterns = rawPatternInputs.map(input => normalizePathLikeInput(input).replace(/\\\\/g, \"/\"));\n\t\t\tconst aliasResolvedPatterns = this.#rootPathAlias\n\t\t\t\t? rawPatterns.map(pattern => (/^\\/+$/.test(pattern) ? \".\" : pattern))\n\t\t\t\t: rawPatterns;\n\t\t\tif (aliasResolvedPatterns.some(pattern => /^\\/+$/.test(pattern))) {\n\t\t\t\tthrow new ToolError(\"Searching from root directory '/' is not allowed\");\n\t\t\t}\n\t\t\tconst internalRouter = InternalUrlRouter.instance();\n\t\t\tconst normalizedPatterns: string[] = [];\n\t\t\tfor (const rawPattern of aliasResolvedPatterns) {\n\t\t\t\tif (!internalRouter.canHandle(rawPattern)) {\n\t\t\t\t\tnormalizedPatterns.push(rawPattern);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (isSshUrl(rawPattern)) {\n\t\t\t\t\tthrow new ToolError(\n\t\t\t\t\t\t`find cannot operate on a remote ssh:// path: ${rawPattern}. ssh:// has no local file to glob; use \\`read ${rawPattern}\\` to list or inspect the remote path.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (hasGlobPathChars(rawPattern)) {\n\t\t\t\t\tif (!/^memory:\\/\\//i.test(rawPattern)) {\n\t\t\t\t\t\tthrow new ToolError(`Glob patterns are not supported for internal URLs: ${rawPattern}`);\n\t\t\t\t\t}\n\t\t\t\t\tconst memoryGlob = splitMemoryGlobPattern(rawPattern);\n\t\t\t\t\tconst resource = await internalRouter.resolve(memoryGlob.baseUrl, {\n\t\t\t\t\t\tcwd: this.session.cwd,\n\t\t\t\t\t\tsettings: this.session.settings,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\tsessionFile: this.session.getSessionFile() ?? undefined,\n\t\t\t\t\t\tlocalProtocolOptions: this.session.localProtocolOptions,\n\t\t\t\t\t\tskills: this.session.skills,\n\t\t\t\t\t\tpathOnly: true,\n\t\t\t\t\t});\n\t\t\t\t\tif (!resource.sourcePath) {","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/glob.ts#L196-L232","documentation":"When a glob/find path entry is an internal URL the router can handle, ssh:// targets are explicitly rejected: a remote ssh path has no local filesystem to glob, so pattern matching is meaningless. The message directs you to the read tool, which can list/inspect remote paths.","triggerScenarios":"Passing path: 'ssh://host/path' (optionally with glob chars) to the glob/find tool; isSshUrl(rawPattern) is true for the routed entry.","commonSituations":"Copy-pasting an ssh remote URL from git config into a find call; assuming glob works over ssh remotes; scripted exploration of remote hosts with the wrong tool.","solutions":["Use the read tool for the ssh path: read 'ssh://host/path' instead of find","Run find/glob on the remote host itself over ssh","Glob only local paths or supported internal schemes (e.g. memory://)"],"exampleFix":"// before\nawait findTool({ path: \"ssh://host/var/log\" });\n// after\nawait readTool({ path: \"ssh://host/var/log\" });","handlingStrategy":"validation","validationCode":"import { isSshUrl } from \"...\";\nif (typeof path === \"string\" && isSshUrl(path)) {\n  // route to the read tool instead of find\n  return readTool({ path });\n}","typeGuard":"const isSshTarget = (p: string): boolean => /^ssh:\\/\\//i.test(p);","tryCatchPattern":"try {\n  await globTool({ path: target });\n} catch (err) {\n  if (err instanceof ToolError && /ssh:\\/\\//.test(err.message)) {\n    return readTool({ path: target });\n  } else throw err;\n}","preventionTips":["Route ssh:// targets to read, never glob/find","Detect the ssh:// prefix in input preprocessing and pick the right tool","Glob remotely on the host itself rather than through this local tool"],"tags":["ssh","unsupported-operation","path"],"backgroundTag":"unsupported-scheme-operation","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}