firecrawl/open-lovable · error · Error
Unable to read file
Error message
Unable to read file: ${normalizedPath} What it means
readFileFromSandbox tries one or more mechanisms (provider readFile API, shell cat) to read a file from the sandbox and throws this error if every attempt fails or returns non-zero exit. It signals the requested file could not be retrieved from the sandbox filesystem, often because it does not exist or the sandbox API is not available.
Solutions
- Verify the file actually exists at that path inside the sandbox (run `ls` or check the file cache) before reading.
- Check for path typos, wrong case, or missing directories in normalizedPath.
- Use the provider's native readFile method instead of the shell fallback.
- Ensure the sandbox object is a supported provider instance (e2b/vercel) exposing commands.run.
- Catch the error and treat it as 'create new file' when the edit should create a missing file.
Example fix
// before
const current = await readFileFromSandbox(sandbox, path);
// after
let current = '';
try {
current = await readFileFromSandbox(sandbox, path);
} catch {
current = ''; // new file: apply edit to empty content
} Defensive patterns
Strategy: try-catch
Validate before calling
const exists = await sandbox.commands.run(`test -f ${fullPath} && echo yes || echo no`, { cwd: '/home/user/app' });
if (exists.stdout.trim() !== 'yes') {
// skip read; treat as new file
} Type guard
function canReadFile(r: unknown): r is { stdout: string; exitCode: number } {
return !!r && typeof r === 'object' && typeof (r as any).stdout === 'string' && typeof (r as any).exitCode === 'number';
} Try / catch
try {
const content = await readFileFromSandbox(sandbox, path);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Unable to read file')) {
console.warn(`File ${path} not readable in sandbox; treating as new file`);
return ''; // or skip this edit
}
throw err;
} Prevention
- Check file existence (test -f or provider list API) before reading.
- Normalize paths consistently (resolve relative to /home/user/app) before every call.
- Keep the sandbox fileCache in sync so cached paths match real sandbox files.
- Handle 'missing file' as create-new-file instead of failing the whole edit batch.
- Log the path and sandbox id on failure to distinguish wrong-path from dead-sandbox issues.
When it happens
Trigger: The file at normalizedPath does not exist inside /home/user/app in the sandbox; `cat` exits non-zero (permissions, missing file); the sandbox object exposes neither a readFile method nor commands.run; or the command output is not a string.
Common situations: Applying an edit to a path that was never created in the sandbox; path casing or typo mismatches (e.g. /src/App.jsx vs app.jsx); sandbox freshly provisioned and empty; using a custom/mock sandbox object lacking the expected API surface.
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 write file via shell
- Failed to list files
- Failed to read file
- Failed to write file via command
- ${data.error}
AI-assisted analysis of firecrawl/open-lovable@69bd93bae7 (2026-08-28).
Data as JSON: /api/errors/eeb9d68278528da6.
Report an issue: GitHub.
Appendix: source
Thrown at lib/morph-fast-apply.ts:115
} catch {}
// fallback to absolute path
try {
const resAbs = await sandbox.runCommand(`cat ${fullPath}`);
if (resAbs && typeof resAbs.stdout === 'string') {
return resAbs.stdout as string;
}
} catch {}
}
// Try shell cat via commands.run
if (sandbox?.commands?.run) {
const result = await sandbox.commands.run(`cat ${fullPath}`, { cwd: '/home/user/app', timeout: 30 });
if (result?.exitCode === 0 && typeof result?.stdout === 'string') {
return result.stdout as string;
}
}
throw new Error(`Unable to read file: ${normalizedPath}`);
}
// Write a file to sandbox and update cache
async function writeFileToSandbox(sandbox: any, normalizedPath: string, fullPath: string, content: string): Promise<void> {
// Provider pattern (writeFile)
if (typeof sandbox?.writeFile === 'function') {
await sandbox.writeFile(normalizedPath, content);
return;
}
// Provider pattern (runCommand redirect)
if (typeof sandbox?.runCommand === 'function') {
// Ensure directory exists
const dir = normalizedPath.includes('/') ? normalizedPath.substring(0, normalizedPath.lastIndexOf('/')) : '';
if (dir) {
try { await sandbox.runCommand(`mkdir -p ${dir}`); } catch {}
}
// Write via heredoc with proper escapingView on GitHub (pinned to 69bd93bae7)