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
- Retry the download after a short delay — empty 200s are often transient upstream faults.
- Verify the URL actually serves the binary (curl -I / curl the URL) and that it is not a placeholder or redirect landing page.
- Check server-side artifact availability (build finished, upload completed) before downloading.
- 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
- Only download artifacts after the producing job/upload is confirmed complete.
- Verify signed URLs are fresh and point at the object, not a redirect landing page.
- Add a bounded retry with backoff for transient upstream empty responses.
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
- file-too-large
- latest-mac.yml is missing artifact path/url.
- Failed to fetch latest-mac.yml (${response.status} ${respons
- Request timed out.
- Timed out waiting for server health
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/ca5b4221ff149c85.
Report an issue: GitHub.