firecrawl/open-lovable · error · Error

Failed to write file via shell: ${normalizedPath}

Error message

Failed to write file via shell: ${normalizedPath}

What it means

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.

Source

Thrown at lib/morph-fast-apply.ts:162

    await sandbox.files.write(fullPath, content);
  } else if (sandbox?.runCode) {
    // Use Python to write safely
    const escaped = content
      .replace(/\\/g, '\\\\')
      .replace(/"""/g, '\"\"\"');
    await sandbox.runCode(`
import os
os.makedirs(os.path.dirname("${fullPath}"), exist_ok=True)
with open("${fullPath}", 'w') as f:
    f.write("""${escaped}""")
print("WROTE:${fullPath}")
    `);
  } else if (sandbox?.commands?.run) {
    // Shell redirection (fallback)
    // Note: beware of special chars; this is a last-resort path
    const result = await sandbox.commands.run(`bash -lc 'mkdir -p "$(dirname "${fullPath}")" && cat > "${fullPath}" << \EOF\n${content}\nEOF'`, { cwd: '/home/user/app', timeout: 60 });
    if (result?.exitCode !== 0) {
      throw new Error(`Failed to write file via shell: ${normalizedPath}`);
    }
  } else {
    throw new Error('No available method to write files to sandbox');
  }

  // Update backend cache if available
  if ((global as any).sandboxState?.fileCache) {
    (global as any).sandboxState.fileCache.files[normalizedPath] = {
      content,
      lastModified: Date.now()
    };
  }
  if ((global as any).existingFiles) {
    (global as any).existingFiles.add(normalizedPath);
  }
}

export async function applyMorphEditToFile(params: {

View on GitHub (pinned to 69bd93bae7)

Solutions

  1. Prefer a sandbox provider exposing a native writeFile API so the shell fallback never runs.
  2. Check the command result's stderr (log result.stdout/stderr before throwing) to see the underlying shell failure.
  3. Escape or strip shell-special characters in content/path, or base64-encode the content and decode on write (`echo <b64> | base64 -d > file`).
  4. Verify the target directory is writable in the sandbox (not read-only, correct user permissions).
  5. Wrap in try/catch to surface the underlying command output to the caller for diagnosis.

Example fix

// before
await sandbox.commands.run(`bash -lc 'mkdir -p "$(dirname "${fullPath}")" && cat > "${fullPath}" << \EOF\n${content}\nEOF'`, ...);
// after
const encoded = Buffer.from(content).toString('base64');
await sandbox.commands.run(`bash -lc 'mkdir -p "$(dirname "${fullPath}")" && echo ${encoded} | base64 -d > "${fullPath}"'`, { cwd: '/home/user/app', timeout: 60 });
Defensive patterns

Strategy: validation

Validate before calling

if (!/^[-\w./]+$/.test(fullPath)) {
  throw new Error(`Unsafe path for shell write: ${fullPath}`);
}
if (/^(EOF|[`$"])/m.test(content) || content.includes('\\')) {
  // use base64 encoding instead of heredoc
}

Try / catch

try {
  await writeFileToSandbox(sandbox, normalizedPath, fullPath, content);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Failed to write file via shell')) {
    const result = await sandbox.commands.run(`ls -ld $(dirname ${fullPath})`, { cwd: '/home/user/app' });
    console.error(`Shell write failed; dir state: ${result?.stdout}, cause: ${err.message}`);
    return retryWithEncodedWrite(); // base64-encoded retry
  }
  throw err;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of firecrawl/open-lovable@69bd93bae7 (2026-08-28). Data as JSON: /api/errors/67915d54c250b6af. Report an issue: GitHub.