{"record":{"id":"67915d54c250b6af","repo":"firecrawl/open-lovable","slug":"failed-to-write-file-via-shell-normalizedpath","errorCode":null,"errorMessage":"Failed to write file via shell: ${normalizedPath}","messagePattern":"Failed to write file via shell: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/morph-fast-apply.ts","lineNumber":162,"sourceCode":"    await sandbox.files.write(fullPath, content);\n  } else if (sandbox?.runCode) {\n    // Use Python to write safely\n    const escaped = content\n      .replace(/\\\\/g, '\\\\\\\\')\n      .replace(/\"\"\"/g, '\\\"\\\"\\\"');\n    await sandbox.runCode(`\nimport os\nos.makedirs(os.path.dirname(\"${fullPath}\"), exist_ok=True)\nwith open(\"${fullPath}\", 'w') as f:\n    f.write(\"\"\"${escaped}\"\"\")\nprint(\"WROTE:${fullPath}\")\n    `);\n  } else if (sandbox?.commands?.run) {\n    // Shell redirection (fallback)\n    // Note: beware of special chars; this is a last-resort path\n    const result = await sandbox.commands.run(`bash -lc 'mkdir -p \"$(dirname \"${fullPath}\")\" && cat > \"${fullPath}\" << \\EOF\\n${content}\\nEOF'`, { cwd: '/home/user/app', timeout: 60 });\n    if (result?.exitCode !== 0) {\n      throw new Error(`Failed to write file via shell: ${normalizedPath}`);\n    }\n  } else {\n    throw new Error('No available method to write files to sandbox');\n  }\n\n  // Update backend cache if available\n  if ((global as any).sandboxState?.fileCache) {\n    (global as any).sandboxState.fileCache.files[normalizedPath] = {\n      content,\n      lastModified: Date.now()\n    };\n  }\n  if ((global as any).existingFiles) {\n    (global as any).existingFiles.add(normalizedPath);\n  }\n}\n\nexport async function applyMorphEditToFile(params: {","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/firecrawl/open-lovable/blob/69bd93bae7a9c97ef989eb70aabe6797fb3dac89/lib/morph-fast-apply.ts#L144-L180","documentation":"writeFileToSandbox falls back to shell redirection (a heredoc via bash -lc) when no provider-native write API exists, and throws this error if that shell command exits non-zero. It means the file content could not be written into the sandbox filesystem. Because the path is interpolated into the shell command, shell-hostile content (quotes, backticks, heredoc-delimiter text) can also make the write fail.","triggerScenarios":"The sandbox exposes sandbox.commands.run but neither a writeFile nor another native write method, and the executed `mkdir -p ... cat > file << EOF` command fails — e.g. read-only filesystem, permissions, disk full, or content containing characters that break the heredoc/quoting (backticks, unmatched quotes, a line equal to the EOF delimiter).","commonSituations":"Editing files containing template literals or shell special characters; sandbox volume mounted read-only; content larger than command-length limits; running as a non-root user without write permission to the target directory.","solutions":["Prefer a sandbox provider exposing a native writeFile API so the shell fallback never runs.","Check the command result's stderr (log result.stdout/stderr before throwing) to see the underlying shell failure.","Escape or strip shell-special characters in content/path, or base64-encode the content and decode on write (`echo <b64> | base64 -d > file`).","Verify the target directory is writable in the sandbox (not read-only, correct user permissions).","Wrap in try/catch to surface the underlying command output to the caller for diagnosis."],"exampleFix":"// before\nawait sandbox.commands.run(`bash -lc 'mkdir -p \"$(dirname \"${fullPath}\")\" && cat > \"${fullPath}\" << \\EOF\\n${content}\\nEOF'`, ...);\n// after\nconst encoded = Buffer.from(content).toString('base64');\nawait sandbox.commands.run(`bash -lc 'mkdir -p \"$(dirname \"${fullPath}\")\" && echo ${encoded} | base64 -d > \"${fullPath}\"'`, { cwd: '/home/user/app', timeout: 60 });","handlingStrategy":"validation","validationCode":"if (!/^[-\\w./]+$/.test(fullPath)) {\n  throw new Error(`Unsafe path for shell write: ${fullPath}`);\n}\nif (/^(EOF|[`$\"])/m.test(content) || content.includes('\\\\')) {\n  // use base64 encoding instead of heredoc\n}","typeGuard":null,"tryCatchPattern":"try {\n  await writeFileToSandbox(sandbox, normalizedPath, fullPath, content);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Failed to write file via shell')) {\n    const result = await sandbox.commands.run(`ls -ld $(dirname ${fullPath})`, { cwd: '/home/user/app' });\n    console.error(`Shell write failed; dir state: ${result?.stdout}, cause: ${err.message}`);\n    return retryWithEncodedWrite(); // base64-encoded retry\n  }\n  throw err;\n}","preventionTips":["Base64-encode file content before shell writes to avoid quoting/heredoc breakage.","Prefer sandbox providers with a native writeFile API; reserve shell redirection as last resort.","Verify the target directory is writable (not read-only mount) in sandbox setup.","Log command stdout/stderr on failure instead of only the path.","Check sandbox disk usage for large content writes."],"tags":["filesystem","sandbox","shell","io"],"backgroundTag":"file-write-failed","analyzedSha":"69bd93bae7a9c97ef989eb70aabe6797fb3dac89","analyzedAt":"2026-08-28T22:20:32.339Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}