can1357/oh-my-pi · error · ToolError
Cannot find internal URL without a backing file
Error message
Cannot find internal URL without a backing file: ${rawPattern} What it means
Non-glob internal URL path entries are resolved to their backing file path via InternalUrlRouter.resolve with pathOnly: true. If the resolved resource has no sourcePath, there is no local file to substitute into the search, so the tool throws with the offending rawPattern in the message.
Solutions
- Ensure the internal URL points to a file-backed resource and the session has the right localProtocolOptions/skills
- Use the direct path or read tool for virtual resources that cannot be globbed
- Fix the URL so InternalUrlRouter.resolve returns a resource with sourcePath
Example fix
// before
await findTool({ path: "skill://virtual-resource" }); // no backing file
// after
await findTool({ path: "skill://real-skill/README.md" }); Defensive patterns
Strategy: type-guard
Validate before calling
const resource = await internalRouter.resolve(url, { cwd, settings, signal, pathOnly: true });
if (!resource.sourcePath) throw new Error(`no backing file for ${url}`); Type guard
const hasBackingFile = (r: { sourcePath?: string | null }): r is { sourcePath: string } =>
typeof r.sourcePath === "string" && r.sourcePath.length > 0; Try / catch
try {
await globTool({ path: internalUrl });
} catch (err) {
if (err instanceof ToolError && /without a backing file/.test(err.message)) {
// use read on the virtual resource or correct the URL
} else throw err;
} Prevention
- Only pass internal URLs that map to real files into find/glob
- Check the session's localProtocolOptions/skills registration for the scheme
- Fall back to the read tool for virtual resources
When it happens
Trigger: Passing a bare internal URL (e.g. 'skill://foo' without glob chars) that resolves to a resource without a sourcePath — scheme targets without an on-disk representation.
Common situations: Referencing generated/virtual resources that exist only in memory; typo'd internal URLs; using a scheme whose handler doesn't map to files in the current session (missing localProtocolOptions/skills).
Related errors
- Path " " uses internal scheme " " and must be resolved…
- Absolute paths are not allowed in omp:// URLs
- ACP cwd must be absolute
- app.path must be absolute
- Archive file ' ' not found
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/5dfa36a6aa20c0f7.
Report an issue: GitHub.
Appendix: source
Thrown at packages/coding-agent/src/tools/glob.ts:250
if (!resource.sourcePath) {
throw new ToolError(`Cannot find internal URL without a backing file: ${memoryGlob.baseUrl}`);
}
normalizedPatterns.push(
path.join(resource.sourcePath.replace(/[*?[{]/g, "[$&]"), memoryGlob.globPattern),
);
continue;
}
const resource = await internalRouter.resolve(rawPattern, {
cwd: this.session.cwd,
settings: this.session.settings,
signal,
sessionFile: this.session.getSessionFile() ?? undefined,
localProtocolOptions: this.session.localProtocolOptions,
skills: this.session.skills,
pathOnly: true,
});
if (!resource.sourcePath) {
throw new ToolError(`Cannot find internal URL without a backing file: ${rawPattern}`);
}
normalizedPatterns.push(resource.sourcePath);
}
if (normalizedPatterns.some(pattern => pattern.length === 0)) {
throw new ToolError("`path` must contain non-empty globs or paths");
}
// Tolerate missing entries in a multi-path call: skip ones whose base
// directory is gone, and only error if every entry is missing. Single
// missing path keeps the original ENOENT semantics — the user explicitly
// asked about that one path, so silent empty results would be misleading.
let missingPaths: string[] = [];
let effectivePatterns = normalizedPatterns;
if (normalizedPatterns.length > 1 && !this.#customOps) {
const partition = await partitionExistingPaths(normalizedPatterns, this.session.cwd, parseFindPattern);
if (partition.valid.length === 0) {
throw new ToolError(`Path not found: ${partition.missing.join(", ")}`);
}View on GitHub (pinned to 9690622007)