different-ai/openwork · error
destination-exists
destination-exists
Error message
Download destination already exists.
What it means
downloadBinaryToPath creates the destination exclusively with open(path, "wx"), which never follows a final symlink; an EEXIST is converted to the coded error 'destination-exists'. This prevents silently overwriting user files and blocks symlink attacks on the destination path. The destination must also resolve inside the authorized roots before this check.
Source
Thrown at apps/desktop/electron/binary-transfer.mjs:322
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();
const { bytesRead } = await stagingFile.read(buffer, 0, Math.min(buffer.length, bytes - position), position);
if (bytesRead === 0) {
throw transferError("Downloaded data changed while it was being saved.", "size-mismatch");
}
await writeAll(destinationFile, buffer.subarray(0, bytesRead));
position += bytesRead;
}
await destinationFile.sync();
await destinationFile.close();
destinationFile = undefined;View on GitHub (pinned to 2b7df46e8a)
Solutions
- Delete or rename the existing file first (fs.rm / rename) if overwriting is intended.
- Pick a unique destinationPath (timestamp/UUID suffix or version in the filename).
- Add an existence check before the call and branch: skip, resume, or overwrite explicitly.
- Serialize concurrent workers so only one downloads to a given path.
Example fix
// before
await downloadBinaryToPath({ url, destinationPath });
// after
import { rm } from "node:fs/promises";
await rm(destinationPath, { force: true }); // explicit overwrite intent
await downloadBinaryToPath({ url, destinationPath }); Defensive patterns
Strategy: validation
Validate before calling
import { lstat } from "node:fs/promises";
let exists = false;
try { await lstat(destinationPath); exists = true; } catch (e) { if (e.code !== "ENOENT") throw e; }
if (exists) throw new Error(`Choose another destination; ${destinationPath} already exists`); Type guard
async function isFreeDestination(p) {
try { await lstat(p); return false; } catch (e) { return e.code === "ENOENT"; }
} Try / catch
try {
await downloadBinaryToPath({ url, destinationPath });
} catch (e) {
if (e?.code === "destination-exists") {
return { ok: false, reason: "exists", path: destinationPath };
}
throw e;
} Prevention
- Check lstat on the destination and branch (skip/rename/overwrite) before downloading.
- Use unique filenames (version/hash/UUID) for generated artifacts.
- Serialize or lock concurrent workers writing to the same destination.
When it happens
Trigger: Calling downloadBinaryToPath with destinationPath pointing at a path that already exists (file, or dangling/symlinked entry) — open("wx") raises EEXIST which is remapped to this error.
Common situations: Re-running a setup script that already downloaded the file; two concurrent workers downloading to the same path; stale artifact from a previous version; a symlink planted at the destination path.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- size-mismatch
- ${result}
- Failed to write .opencode/openwork.json
- Environment variable store could not be read
- Environment variable store is invalid JSON
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/7ada1f1eeedb40e5.
Report an issue: GitHub.