can1357/oh-my-pi · error
File not found: ${filePath}
Error message
File not found: ${filePath} What it means
resolveSymbolColumn wraps its file read in try/catch; when the read fails with ENOENT (file does not exist), it rethrows as a plain, human-readable 'File not found' error naming the path instead of leaking the raw filesystem error.
Source
Thrown at packages/coding-agent/src/lsp/utils.ts:719
if (!symbolSpec) {
return firstNonWhitespaceColumn(targetLine);
}
const { symbol, occurrence } = parseSymbolSpec(symbolSpec);
const exactIndexes = findSymbolMatchIndexes(targetLine, symbol);
const fallbackIndexes = exactIndexes.length > 0 ? exactIndexes : findSymbolMatchIndexes(targetLine, symbol, true);
if (fallbackIndexes.length === 0) {
throw new Error(`Symbol "${symbol}" not found on line ${lineNumber}`);
}
if (occurrence > fallbackIndexes.length) {
throw new Error(
`Symbol "${symbol}" occurrence ${occurrence} is out of bounds on line ${lineNumber} (found ${fallbackIndexes.length})`,
);
}
return fallbackIndexes[occurrence - 1];
} catch (error) {
if (isEnoent(error)) {
throw new Error(`File not found: ${filePath}`);
}
throw error;
}
}
export async function readLocationContext(filePath: string, line: number, contextLines = 1): Promise<string[]> {
const targetLine = Math.max(1, line);
const surrounding = Math.max(0, contextLines);
try {
const fileText = await Bun.file(filePath).text();
const lines = fileText.split("\n");
if (lines.length === 0) return [];
const startLine = Math.max(1, targetLine - surrounding);
const endLine = Math.min(lines.length, targetLine + surrounding);
const context: string[] = [];
for (let currentLine = startLine; currentLine <= endLine; currentLine++) {
const content = lines[currentLine - 1] ?? "";View on GitHub (pinned to 9690622007)
Solutions
- Verify the file exists at the given path and pass an absolute or project-relative path that resolves correctly.
- Re-check for recent renames/deletes (git status) and update the path.
- Run the tool from the correct working directory or pass a path relative to the project root.
Example fix
// before
await lspTool.execute({ action: "hover", file: "src/a.ts", line: 3 }); // wrong cwd
// after
await lspTool.execute({ action: "hover", file: "packages/app/src/a.ts", line: 3 }); Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "node:fs/promises";
import * as path from "node:path";
async function assertFileExists(p: string) {
const abs = path.resolve(p);
await fs.access(abs, fs.constants.R_OK);
return abs;
}
// await assertFileExists(params.file) before calling the tool Try / catch
try {
return await lspTool.execute({ action: "hover", file, line });
} catch (err) {
if (err instanceof Error && err.message.startsWith("File not found:")) {
// resolve against project root or prompt user for correct path
return lspTool.execute({ action: "hover", file: path.join(projectRoot, file), line });
} throw err;
} Prevention
- Validate file paths against the project root before calling LSP tools.
- Use absolute paths or paths verified to exist to avoid cwd ambiguity.
- Refresh paths after renames/deletes (check git status).
When it happens
Trigger: Calling any LSP tool action with a `file` path that does not exist on disk (after resolving relative to the project dir) — the readLocationContext/resolveSymbolColumn read hits ENOENT.
Common situations: Typos or wrong relative paths in tool params; file deleted or renamed after the agent read the plan; paths expressed against the wrong working directory (e.g. repo root vs package dir); Windows/POSIX path separator confusion.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- ${name} path does not exist: ${trimmed}
- Managed skill "${name}" SKILL.md is not a regular file; refu
- Shared-folder destination escapes its configured root
- Snippet file not found: ${resolved}
- Path is not a file: ${pathArg}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/87086b64e4217607.
Report an issue: GitHub.