vercel/ai · error
File not found: ${inputPath}
Error message
File not found: ${inputPath} What it means
Thrown by readFile when the path resolved and passed the existence check, but the sandbox's readTextFile returned null/undefined — meaning the file could not actually be read as text (e.g. it is a directory, a binary file, or was removed between the check and the read). The library reports it as 'File not found' with the caller's original input path.
Source
Thrown at packages/harness-cline/src/cline-remote-ops.ts:203
}
const resolvedPath = lastOutputLine(result.output);
if (!resolvedPath) {
throw new Error(`Unable to resolve path: ${inputPath}`);
}
return assertWorkspacePath(resolvedPath);
};
const readFile = async (inputPath: string): Promise<string> => {
const remotePath = resolvePath(inputPath);
const resolved = await resolveReadableSandboxPath({
remotePath,
inputPath,
missingMessage: `File not found: ${inputPath}`,
});
const content = await sandbox.readTextFile({ path: resolved });
if (content == null) {
throw new Error(`File not found: ${inputPath}`);
}
return content;
};
const writeFile = async (
inputPath: string,
content: string,
): Promise<void> => {
const remotePath = resolvePath(inputPath);
const resolved = await resolveWritableSandboxPath({
remotePath,
inputPath,
});
// `writeTextFile` creates parent directories recursively per the
// SandboxSession contract, so no explicit mkdir is needed.
await sandbox.writeTextFile({ path: resolved, content });
};
View on GitHub (pinned to 69428b1f8b)
Solutions
- Check that the path targets a regular file, not a directory (use ops.ls or ops.bash with `test -f`).
- For binary content, do not use readFile — copy or inspect the file via ops.bash commands instead.
- Retry the read once if the file was concurrently modified; otherwise re-list the directory to find the correct file name.
- Verify sandbox file permissions allow the session user to read the file.
Example fix
// before: reading a directory
const content = await ops.readFile('src'); // File not found: src
// after: only read regular files
const entries = await ops.ls('src');
const content = await ops.readFile(`src/${entries[0]}`); Defensive patterns
Strategy: try-catch
Validate before calling
async function isRegularTextFile(ops, p) {
const r = await ops.bash(`test -f ${JSON.stringify(p)} && echo file || echo notfile`);
return r.output.includes('file');
} Try / catch
try {
return await ops.readFile(path);
} catch (e) {
if (e instanceof Error && e.message.startsWith('File not found:')) {
const parent = path.posix.dirname(path);
const entries = await ops.ls(parent); // discover the real name
return ops.readFile(`${parent}/${entries.find(x => x === path.posix.basename(path)) ?? entries[0]}`);
}
throw e;
} Prevention
- Never pass directory paths to readFile — check with `test -f` when unsure.
- Treat readFile as text-only; use bash commands for binary content.
- Re-list the directory when a path fails; names may have changed.
- Verify sandbox permissions allow the session user to read target files.
When it happens
Trigger: readFile('notes/') where the path points at a directory; readFile on a binary file that readTextFile refuses to decode; a race where the file is deleted between resolveReadableSandboxPath and readTextFile; a sandbox that returns null for unreadable/permission-denied files.
Common situations: Model-driven tool calls reading directories as if they were files; reading binary artifacts (images, compiled output) that only support text reads; TOCTOU races in active sandboxes; permissions restricted inside the sandbox container.
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
- `Failed to create sandbox work directory ${workDir} (exit ${
- Cannot write harness skill '${skillName}': ${skillDir} alrea
- ${errorMessage} (exit ${result.exitCode})${result.stderr ? `
- Invalid argument for parameter batch: batch must be a suppor
- Sandbox session is not available
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/8c5b9319e8af5d16.
Report an issue: GitHub.