can1357/oh-my-pi · error · Error

Path is not a file: ${pathArg}

Error message

Path is not a file: ${pathArg}

What it means

The delete tool only removes regular files. If stat succeeds but the entry is a directory, symlink-to-directory, socket, FIFO, or device, the operation refuses with this message rather than recursing or unlinking something unexpected.

Source

Thrown at packages/coding-agent/src/cursor.ts:355

	if (refusal) {
		return createToolResultMessage(toolCallId, toolName, buildToolErrorResult(refusal), true);
	}

	options.emitEvent?.({ type: "tool_execution_start", toolCallId, toolName, args: { path: pathArg } });

	const absolutePath = resolveToCwd(pathArg, options.getCwd?.() ?? options.cwd);
	let isError = false;
	let result: AgentToolResult<unknown>;

	try {
		let fileStat: fs.Stats | undefined;
		try {
			fileStat = fs.statSync(absolutePath);
		} catch {
			throw new Error(`File not found: ${pathArg}`);
		}
		if (!fileStat.isFile()) {
			throw new Error(`Path is not a file: ${pathArg}`);
		}

		fs.rmSync(absolutePath);

		const sizeText = fileStat.size ? ` (${fileStat.size} bytes)` : "";
		const message = `Deleted ${pathArg}${sizeText}`;
		result = { content: [{ type: "text", text: message }], details: {} };
	} catch (error) {
		const message = error instanceof Error ? error.message : String(error);
		result = buildToolErrorResult(message);
		isError = true;
	}

	options.emitEvent?.({ type: "tool_execution_end", toolCallId, toolName, result, isError });
	return createToolResultMessage(toolCallId, toolName, result, isError);
}

function decodeToolCallId(toolCallId?: string): string {

View on GitHub (pinned to 9690622007)

Solutions

  1. If you intend to remove a directory, use the bash/shell tool with `rm -r <dir>` instead of the file-delete tool.
  2. Point pathArg at an individual regular file inside the directory.
  3. Check what the path is with `ls -la <path>` / `stat <path>` before deleting.

Example fix

// before
await execDelete("dist");  // dist is a directory
// after (shell tool)
await bash("rm -r dist");
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from "node:fs";
const s = statSync(absolutePath, { throwIfNoEntry: false });
if (s && !s.isFile()) throw new Error(`${absolutePath} is not a regular file; use rm -r for directories`);

Type guard

function isFileStat(s: import("node:fs").Stats | undefined): s is import("node:fs").Stats & { isFile(): true } {
  return !!s && s.isFile();
}

Try / catch

try {
  await execDelete(pathArg);
} catch (e) {
  if (String(e.message).startsWith("Path is not a file")) {
    // route directories to `rm -r` via the shell tool instead
  } else throw e;
}

Prevention

When it happens

Trigger: pathArg resolves to an existing directory (most common), a special file, or a symlink pointing at a directory, in the executeDelete path.

Common situations: Asking the agent to 'delete the build folder' through the file-delete tool instead of a shell command; passing a directory that was expected to be a file after a refactor.

Related errors


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