can1357/oh-my-pi · error · ToolError

:// URL resolved without a filesystem path and cannot be…

Error message

${scheme}:// URL resolved without a filesystem path and cannot be used in bash: ${url}

What it means

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.

Solutions

  1. Materialize the resource to a real file first (e.g. write it via a tool that supports it) and reference that path in bash.
  2. Fix or update the plugin handler so it returns a sourcePath for pathOnly requests.
  3. Use a scheme with filesystem backing (skill://, local://, attachment://) in bash commands.
  4. If you control the handler, ensure InternalResource.sourcePath is always populated for bash-capable resources.
Defensive patterns

Strategy: fallback

Try / catch

try { await expandInternalUrls(cmd, ctx); } catch (e) { if (e instanceof ToolError && /resolved without a filesystem path/.test(e.message)) materializeResourceToFile(e); else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/62e860640a56e021. Report an issue: GitHub.

Appendix: source

Thrown at packages/coding-agent/src/tools/bash-skill-urls.ts:311

	}

	if (!internalRouter?.canHandle(url)) {
		throw new ToolError(
			`Cannot resolve ${scheme}:// URL in bash command: ${url}\n` +
				"Internal URL router is unavailable for this protocol in the current session.",
		);
	}

	let resource: InternalResource;
	try {
		resource = await internalRouter.resolve(url, { cwd, pathOnly: true, sessionFile });
	} catch (error) {
		const message = error instanceof Error ? error.message : String(error);
		throw new ToolError(`Failed to resolve ${scheme}:// URL in bash command: ${url}\n${message}`);
	}

	if (!resource.sourcePath) {
		throw new ToolError(`${scheme}:// URL resolved without a filesystem path and cannot be used in bash: ${url}`);
	}

	return path.resolve(resource.sourcePath);
}

/**
 * Expand all skill:// URIs in a bash command string.
 * Returns the command with URIs replaced by shell-escaped absolute paths.
 * Throws ToolError if any URI cannot be resolved.
 */
export function expandSkillUrls(command: string, skills: readonly Skill[]): string {
	if (skills.length === 0 || !command.includes("skill://")) {
		return command;
	}

	return command.replace(SKILL_URL_PATTERN, token => {
		const url = unquoteToken(token);
		const resolvedPath = resolveSkillUrlToPath(url, skills);

View on GitHub (pinned to 9690622007)