different-ai/openwork · error

zero-byte-file

zero-byte-file

Error message

Download response was empty.

What it means

After the response body stream completes, downloadBinaryToPath throws code 'zero-byte-file' if no bytes at all were received. An empty body means there is no binary to save, so the operation fails rather than creating an empty destination file. This indicates an upstream server/CDN problem, not a local one.

Source

Thrown at apps/desktop/electron/binary-transfer.mjs:312

    await mkdir(stagingDir, { recursive: true });
    stagingPath = path.join(stagingDir, `download-${randomUUID()}.part`);
    stagingFile = await open(stagingPath, "wx+");
    const reader = response.body?.getReader();
    let bytes = 0;
    if (reader) {
      while (true) {
        signal?.throwIfAborted();
        const { done, value } = await reader.read();
        if (done) break;
        bytes += value.byteLength;
        if (bytes > maxBytes) {
          await reader.cancel();
          throw transferError(`Download exceeds the ${maxBytes}-byte limit.`, "file-too-large");
        }
        await writeAll(stagingFile, value);
      }
    }
    if (bytes === 0) throw transferError("Download response was empty.", "zero-byte-file");
    // Only a complete download reaches the workspace. Revalidate the
    // destination, create it exclusively ("wx" never follows a final
    // symlink), and prove by device and inode that the created file resides
    // inside the authorized root before a single byte is written to it.
    await resolveAuthorizedPath(input?.destinationPath, options?.authorizedRoots);
    try {
      destinationFile = await open(destinationPath, "wx");
    } catch (error) {
      if (error?.code === "EEXIST") {
        throw transferError("Download destination already exists.", "destination-exists");
      }
      throw error;
    }
    await verifyOpenFileWithinRoot(destinationFile, destinationPath, destination.rootRealPath, "Download destination");
    const buffer = Buffer.allocUnsafe(1024 * 1024);
    let position = 0;
    while (position < bytes) {
      signal?.throwIfAborted();

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Retry the download after a short delay — empty 200s are often transient upstream faults.
  2. Verify the URL actually serves the binary (curl -I / curl the URL) and that it is not a placeholder or redirect landing page.
  3. Check server-side artifact availability (build finished, upload completed) before downloading.
  4. If the resource can legitimately be empty, gate the call: only download when size/content-length > 0.

Example fix

// before
await downloadBinaryToPath({ url, destinationPath });
// after
const head = await fetch(url, { method: "HEAD" });
const size = Number(head.headers.get("content-length") ?? 0);
if (size > 0) await downloadBinaryToPath({ url, destinationPath });
else throw new Error(`Artifact at ${url} is empty upstream; check the server.`);
Defensive patterns

Strategy: retry

Validate before calling

const head = await fetch(url, { method: "HEAD" });
const len = Number(head.headers.get("content-length"));
if (head.ok && len === 0) throw new Error(`Upstream artifact at ${url} is empty; do not download yet`);

Type guard

function isDownloadableHead(head) {
  return head.ok && Number(head.headers.get("content-length") ?? "0") > 0;
}

Try / catch

try {
  await downloadBinaryToPath({ url, destinationPath });
} catch (e) {
  if (e?.code === "zero-byte-file") {
    await sleep(2000);
    return downloadBinaryToPath({ url, destinationPath }); // bounded retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling downloadBinaryToPath against a URL that returns response.ok with a zero-length body (empty 200 response), after the read loop ends with bytes === 0.

Common situations: CDN or proxy returning empty bodies on transient faults; URLs that redirect to an empty success page; server-side job not finished so the artifact endpoint returns an empty 200; expired signed URLs yielding empty success responses.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/ca5b4221ff149c85. Report an issue: GitHub.