can1357/oh-my-pi · error · ToolError

Searching from root directory '/' is not allowed

Error message

Searching from root directory '/' is not allowed

What it means

The glob/find tool resolves its path entries and refuses to search from the filesystem root '/'. Searching '/' would traverse the entire system, so any pattern that reduces to '/' (or repeated slashes) is rejected with a ToolError before any globbing happens.

Source

Thrown at packages/coding-agent/src/tools/glob.ts:204

		const preparationController = !this.#customOps?.glob && signal ? new AbortController() : undefined;
		const abortPreparation = (): void => preparationController?.abort();
		if (preparationController && signal) {
			signal.addEventListener("abort", abortPreparation, { once: true });
		}
		const immediateAbortSignal = this.#customOps?.glob ? signal : preparationController?.signal;
		const execution = untilAborted(immediateAbortSignal, async () => {
			const formatScopePath = (targetPath: string): string => formatPathRelativeToCwd(targetPath, this.session.cwd);
			const scopedPaths = toPathList(pathInput);
			const effectivePaths = scopedPaths.length > 0 ? scopedPaths : ["."];
			const rawPatternInputs = this.#customOps
				? effectivePaths
				: await expandDelimitedPathEntries(effectivePaths, this.session.cwd, { splitter: parseFindPattern });
			const rawPatterns = rawPatternInputs.map(input => normalizePathLikeInput(input).replace(/\\/g, "/"));
			const aliasResolvedPatterns = this.#rootPathAlias
				? rawPatterns.map(pattern => (/^\/+$/.test(pattern) ? "." : pattern))
				: rawPatterns;
			if (aliasResolvedPatterns.some(pattern => /^\/+$/.test(pattern))) {
				throw new ToolError("Searching from root directory '/' is not allowed");
			}
			const internalRouter = InternalUrlRouter.instance();
			const normalizedPatterns: string[] = [];
			for (const rawPattern of aliasResolvedPatterns) {
				if (!internalRouter.canHandle(rawPattern)) {
					normalizedPatterns.push(rawPattern);
					continue;
				}
				if (isSshUrl(rawPattern)) {
					throw new ToolError(
						`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.`,
					);
				}
				if (hasGlobPathChars(rawPattern)) {
					if (!/^memory:\/\//i.test(rawPattern)) {
						throw new ToolError(`Glob patterns are not supported for internal URLs: ${rawPattern}`);
					}
					const memoryGlob = splitMemoryGlobPattern(rawPattern);

View on GitHub (pinned to 9690622007)

Solutions

  1. Search from the project root instead: omit path or use '.' / the workspace directory
  2. Scope the search to a subdirectory, e.g. 'src'
  3. Do not pass a bare '/' path entry; expand it to a concrete directory

Example fix

// before
await globTool({ pattern: "*.ts", path: "/" });
// after
await globTool({ pattern: "*.ts", path: "src" });
Defensive patterns

Strategy: validation

Validate before calling

const entries = Array.isArray(path) ? path : [path];
if (entries.some(e => /^\/+$/.test(e))) throw new Error("refusing to search from root '/'; pass '.' or a scoped directory");

Type guard

const isScopedSearchPath = (p: string): boolean => p.length > 0 && !/^\/+$/.test(p);

Try / catch

try {
  await globTool({ pattern, path });
} catch (err) {
  if (err instanceof ToolError && /root directory/.test(err.message)) {
    await globTool({ pattern, path: "." });
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the glob/find tool with path '/' or '//' (after alias resolution, root-path aliases map bare '/' to '.' only when #rootPathAlias is set; otherwise it throws).

Common situations: Default-empty path variable rendering as '/'; users expecting '/'-rooted search to be sandboxed to the workspace; config that sets searchPath to os.tmpdir-like '/' fallbacks.

Related errors


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