can1357/oh-my-pi · error · ToolError
Cannot ${internalUrlAction} a remote ssh:// path (no local f
Error message
Cannot ${internalUrlAction} a remote ssh:// path (no local file): ${rawPath}. Use \`read ${rawPath}\` to view it, or use \`grep\` on a specific remote file. What it means
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.
Source
Thrown at packages/coding-agent/src/tools/path-utils.ts:1547
resolvedPathInputs.push(resolved.sourcePath);
if (opts.trackImmutableSources && resolved.immutable) {
immutableSourcePaths.add(path.resolve(resolved.sourcePath));
}
continue;
}
// Resolver missing or declined (e.g. ftp/ws/wss): fail explicitly
// instead of letting the local-path fallthrough surface a confusing
// "Path not found" for a URL-shaped input.
throw new ToolError(
`Cannot ${internalUrlAction} external URL: ${rawPath}. Use \`read\` to fetch web content, then search the returned text.`,
);
}
if (!internalRouter.canHandle(rawPath)) {
resolvedPathInputs.push(rawPath);
continue;
}
if (isSshUrl(rawPath)) {
throw new ToolError(
`Cannot ${internalUrlAction} a remote ssh:// path (no local file): ${rawPath}. Use \`read ${rawPath}\` to view it, or use \`grep\` on a specific remote file.`,
);
}
if (hasGlobPathChars(rawPath)) {
throw new ToolError(`Glob patterns are not supported for internal URLs: ${rawPath}`);
}
const resource = await internalRouter.resolve(rawPath, {
cwd,
settings: opts.settings,
signal: opts.signal,
sessionFile: opts.sessionFile,
localProtocolOptions: opts.localProtocolOptions,
skills: opts.skills,
// Tool-scope resolution only needs `sourcePath`; skip content
// materialization so large artifacts (or any handler that separates
// path from content) stay searchable without OOM risk.
pathOnly: true,
});View on GitHub (pinned to 9690622007)
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.
Example fix
// before
search({ pattern: "FIXME", paths: ["ssh://dev@box/srv/app"] })
// after
await read({ path: "ssh://dev@box/srv/app/src/main.ts" });
// or: git clone ssh://dev@box/srv/app && search({ paths: ["./app"] }) Defensive patterns
Strategy: validation
Validate before calling
if (p.startsWith("ssh://")) {
throw new Error("ssh:// paths cannot back a search scope; use read or clone locally");
} Type guard
const isSshPath = (p) => p.startsWith("ssh://"); Try / catch
try { scope = await resolveToolSearchScope(opts); }
catch (e) {
if (e.message.includes("remote ssh:// path")) {
return read({ path: p }); // degrade to viewing the remote resource
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ssh://: ${target.name} has no verified POSIX shell for ssh:/
- find cannot operate on a remote ssh:// path: ${rawPattern}.
- {}: hard link not allowed for directory
- `{operation}` is not supported on a {} repository
- imageUrls exposure "ssh" requires imageUrls.publicBaseUrl
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/be92cabde4b06510.
Report an issue: GitHub.