firecrawl/open-lovable · error · Error

Failed to read zip file: ${error}

Error message

Failed to read zip file: ${error}

What it means

Thrown when the sandbox command `base64 /tmp/project.zip` exits non-zero while trying to encode the freshly created zip for download. It means the zip either wasn't created by the previous step or can't be read (missing file, missing base64 binary, permissions).

Source

Thrown at app/api/create-zip/route.ts:45

    }
    
    const sizeResult = await global.activeSandbox.runCommand({
      cmd: 'bash',
      args: ['-c', `ls -la /tmp/project.zip | awk '{print $5}'`]
    });
    
    const fileSize = await sizeResult.stdout();
    console.log(`[create-zip] Created project.zip (${fileSize.trim()} bytes)`);
    
    // Read the zip file and convert to base64
    const readResult = await global.activeSandbox.runCommand({
      cmd: 'base64',
      args: ['/tmp/project.zip']
    });
    
    if (readResult.exitCode !== 0) {
      const error = await readResult.stderr();
      throw new Error(`Failed to read zip file: ${error}`);
    }
    
    const base64Content = (await readResult.stdout()).trim();
    
    // Create a data URL for download
    const dataUrl = `data:application/zip;base64,${base64Content}`;
    
    return NextResponse.json({
      success: true,
      dataUrl,
      fileName: 'vercel-sandbox-project.zip',
      message: 'Zip file created successfully'
    });
    
  } catch (error) {
    console.error('[create-zip] Error:', error);
    return NextResponse.json(
      { 

View on GitHub (pinned to 69bd93bae7)

Solutions

  1. Check the `error` field in the message — stderr names the real cause (e.g. 'No such file or directory')
  2. Ensure the zip step succeeded and ran in the same sandbox instance before the base64 step
  3. Verify the file exists first (`test -f /tmp/project.zip`) and fail earlier with a clearer message
  4. Use `base64 -w 0` or `openssl base64` if line-wrapping or binary availability is the problem

Example fix

// before
if (readResult.exitCode !== 0) {
  const error = await readResult.stderr();
  throw new Error(`Failed to read zip file: ${error}`);
}
// after
const check = await global.activeSandbox.runCommand({ cmd: 'bash', args: ['-c', 'test -f /tmp/project.zip && echo ok'] });
if ((await check.stdout()).trim() !== 'ok') {
  throw new Error('/tmp/project.zip missing — zip step failed or sandbox was recreated');
}
if (readResult.exitCode !== 0) {
  const error = await readResult.stderr();
  throw new Error(`Failed to read zip file: ${error}`);
}
Defensive patterns

Strategy: validation

Validate before calling

const exists = await sandbox.runCommand({ cmd: 'bash', args: ['-c', 'test -f /tmp/project.zip && echo yes || echo no'] });
if ((await exists.stdout()).trim() !== 'yes') throw new Error('/tmp/project.zip missing before read step');

Type guard

function commandOk(r: { exitCode: number }): boolean { return r.exitCode === 0; }

Try / catch

try {
  const dataUrl = await downloadProjectZip();
} catch (e) {
  if (e.message.includes('Failed to read zip file')) {
    // re-run the zip step in the same sandbox before giving up
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /api/create-zip where /tmp/project.zip does not exist (the earlier zip step failed silently or ran in a different sandbox), the file is unreadable, or `base64` is unavailable in the image.

Common situations: Sandbox re-created between the zip and read steps so /tmp was wiped; coreutils variant without `base64` (e.g. busybox requiring `base64` args differences); permission errors on /tmp.

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


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