can1357/oh-my-pi · error · NotFoundError
File not found: ${relativePath}
Error message
File not found: ${relativePath} What it means
HashlineFilesystem.readText() resolves the relative path against the session cwd and reads via readEditFileText; ENOENT — and notably also a readEditFileText failure whose message is literally 'File not found: <path>' — is converted to a NotFoundError. This second branch exists because readEditFileText may throw its own 'File not found' Error for cases isEnoent misses (e.g. path inside a non-existent directory reported by the edit-file reader).
Source
Thrown at packages/coding-agent/src/edit/hashline/filesystem.ts:118
// snapshot tag uniquely names. Confine the redirect to locations a plain
// "write" may legitimately target:
// 1. the working tree (the model dropped the directory), or
// 2. the session `local://` sandbox where plan/scratch artifacts live —
// the snapshot tag proves the model wrote/read that exact file this
// session, so a bare `plan.md#tag` should land on `local://plan.md`.
// The secret vault and any other out-of-tree path stay refused.
const root = canonicalSnapshotKey(this.session.cwd);
if (resolvedPath === root || resolvedPath.startsWith(`${root}${path.sep}`)) return true;
return targetsLocalSandbox(this.session, resolvedPath);
}
async readText(relativePath: string): Promise<string> {
const absolutePath = this.resolveAbsolute(relativePath);
let content: string;
try {
content = await readEditFileText(absolutePath, relativePath);
} catch (error) {
if (isEnoent(error)) throw new NotFoundError(relativePath, error);
if (error instanceof Error && error.message === `File not found: ${relativePath}`) {
throw new NotFoundError(relativePath, error);
}
throw error;
}
// Refuse edits against generated files (lockfiles, models.json, …).
assertEditableFileContent(content, relativePath, this.session.settings);
return content;
}
override async readBinary(relativePath: string): Promise<Uint8Array | undefined> {
const absolutePath = this.resolveAbsolute(relativePath);
if (isNotebookPath(absolutePath)) return undefined;
try {
return await fs.readFile(absolutePath);
} catch (error) {
if (isEnoent(error)) throw new NotFoundError(relativePath, error);
throw error;View on GitHub (pinned to 9690622007)
Solutions
- Verify the file exists relative to the session cwd (ls) and correct the relative path.
- Re-read the file listing / re-run read to refresh which files exist, then re-issue.
- If the file should exist but was deleted, restore it or use the write tool to recreate it.
Example fix
// before
edit({ section: `@@@ src/helpers/removed.ts:a1b2\n- x` });
// after
// file was deleted in rebase — target the new location
edit({ section: `@@@ src/utils/helpers.ts:c3d4\n- x\n+ y` }); Defensive patterns
Strategy: try-catch
Validate before calling
import * as path from 'node:path';
const abs = path.resolve(session.cwd, relativePath);
if (!(await Bun.file(abs).exists())) {
throw new Error(`Refusing edit: ${relativePath} does not exist under ${session.cwd}`);
} Try / catch
import { NotFoundError } from '.../filesystem';
try {
const text = await fs.readText(relativePath);
return applyEdit(text);
} catch (e) {
if (e instanceof NotFoundError) {
return { status: 'missing-file', path: relativePath }; // skip or recreate via write
}
throw e;
} Prevention
- Re-list files after git operations (checkout, rebase, clean) before editing.
- Match file name case exactly — Linux is case-sensitive.
- Check for broken symlinks when a path 'should' exist.
When it happens
Trigger: Applying an edit or preview against a relativePath that does not exist under session.cwd: file deleted, wrong relative path, path never created, or edit issued against a file in a removed directory.
Common situations: Stale session state after a git checkout/rebase removed the file; model inventing a path not in its context; case-sensitivity mismatch (Foo.ts vs foo.ts) on Linux.
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
- ${message} || Unable to read ${sectionPath}
- Missing hashline snapshot tag for ${sectionPath}; use `${HL_
- Multiple hashline sections resolve to the same file (${previ
- No hashline sections found in input.
- STOP. Edits to ${path} have been a byte-identical no-op ${co
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/401a312eda217680.
Report an issue: GitHub.