can1357/oh-my-pi · error · ToolError

Directory paths are not supported by read(): ${filePath}

Error message

Directory paths are not supported by read(): ${filePath}

What it means

`resolveRegularFile` stats the resolved path with `Bun.file(...).stat()` before reading; if the target is a directory, `read()` throws this ToolError because `file.text()` cannot return directory content. Only regular files are readable through the sandbox read helper.

Source

Thrown at packages/coding-agent/src/eval/js/shared/helpers.ts:154

	if (normalized.startsWith("..") || normalized.includes("/../") || normalized.includes("/..")) {
		throw new ToolError(`Path traversal (..) is not allowed in ${scheme}:// URLs: ${rawPath}`);
	}
	const resolved = path.resolve(rootPath, normalized);
	if (resolved !== rootPath && !resolved.startsWith(`${rootPath}${path.sep}`)) {
		throw new ToolError(`${scheme}:// path escapes its root: ${rawPath}`);
	}
	return resolved;
}

async function resolveRegularFile(
	ctx: HelperContext,
	rawPath: string,
): Promise<{ filePath: string; file: Bun.BunFile; size: number }> {
	const filePath = resolveHelperPath(ctx, rawPath, "read");
	const file = Bun.file(filePath);
	const stat = await file.stat();
	if (stat.isDirectory()) {
		throw new ToolError(`Directory paths are not supported by read(): ${filePath}`);
	}
	return { filePath, file, size: stat.size };
}

function getDataSize(data: string | Blob | ArrayBuffer | ArrayBufferView): number {
	if (typeof data === "string") return utf8Encoder.encode(data).byteLength;
	if (data instanceof Blob) return data.size;
	if (data instanceof ArrayBuffer) return data.byteLength;
	return data.byteLength;
}

function isWriteData(value: unknown): value is string | Blob | ArrayBuffer | ArrayBufferView {
	return (
		typeof value === "string" || value instanceof Blob || value instanceof ArrayBuffer || ArrayBuffer.isView(value)
	);
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Read a specific file inside the directory, e.g. `read("src/index.ts")`.
  2. If you need directory listing, use the session's file-listing tool (e.g. glob/ls) instead of the read helper.
  3. Verify the target path exists as a file before reading (stat or a filesystem check).

Example fix

// before
const txt = await read("src");
// after
const txt = await read("src/index.ts");
Defensive patterns

Strategy: validation

Validate before calling

const stat = await Bun.file(path).stat();
if (stat?.isDirectory()) throw new Error(`${path} is a directory`);

Try / catch

try {
	return await read(p);
} catch (err) {
	if (String(err?.message).startsWith("Directory paths are not supported")) {
		return await read(path.join(p, "index.ts")); // or surface a listing tool instead
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling `read()` on a directory path — e.g. `read("src")`, `read("local://reports/")` — where the resolved path is an existing directory.

Common situations: Pointing read at a folder expecting it to list contents or concatenate files; stale assumptions after a path became a directory; trailing-slash confusion.

Related errors


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