denoland/deno · error · Error
A file exists at the destination: ${destStr}
Error message
A file exists at the destination: ${destStr} What it means
fs.copyFileSync with fs.constants.COPYFILE_EXCL performs a no-clobber copy: it lstats the destination and, if anything exists there (file, directory, symlink), throws 'A file exists at the destination: ...' - the polyfill's equivalent of Node's EEXIST. Without the flag the destination is silently overwritten.
Source
Thrown at ext/node/polyfills/_fs/_fs_copy.ts:95
export const copyFilePromise = promisify(copyFile) as (
src: string | Buffer | URL,
dest: string | Buffer | URL,
mode?: number,
) => Promise<void>;
export function copyFileSync(
src: string | Buffer | URL,
dest: string | Buffer | URL,
mode?: number,
) {
const srcStr = getValidatedPathToString(src, "src");
const destStr = getValidatedPathToString(dest, "dest");
const modeNum = getValidMode(mode, "copyFile");
if ((modeNum & fs.COPYFILE_EXCL) === fs.COPYFILE_EXCL) {
try {
Deno.lstatSync(destStr);
throw new Error(`A file exists at the destination: ${destStr}`);
} catch (e) {
if (ObjectPrototypeIsPrototypeOf(Deno.errors.NotFound.prototype, e)) {
Deno.copyFileSync(srcStr, destStr);
} else {
throw e;
}
}
} else {
Deno.copyFileSync(srcStr, destStr);
}
}
View on GitHub (pinned to 89f33cbef2)
Solutions
- If overwriting is acceptable, drop the COPYFILE_EXCL flag
- Treat the error as 'already done': catch it and skip/continue
- Pre-check with fs.existsSync(dst) or fs.lstatSync when you need custom handling per case
Example fix
// before
fs.copyFileSync(src, dst, fs.constants.COPYFILE_EXCL); // throws if dst exists
// after
try {
fs.copyFileSync(src, dst, fs.constants.COPYFILE_EXCL);
} catch (e) {
if (
e instanceof Error &&
e.message.startsWith("A file exists at the destination")
) {
// previously copied - treat as success
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
import * as fs from "node:fs";
function copyNoClobber(src: string, dst: string): "copied" | "existed" {
if (fs.existsSync(dst)) return "existed"; // lstat-based pre-check
try {
fs.copyFileSync(src, dst, fs.constants.COPYFILE_EXCL);
return "copied";
} catch {
return "existed"; // lost the race - treat as already present
}
} Try / catch
try {
fs.copyFileSync(src, dst, fs.constants.COPYFILE_EXCL);
} catch (e) {
if (e instanceof Error && e.message.startsWith("A file exists at the destination")) {
// Deno polyfill: plain Error (Node sets code EEXIST) - treat as idempotent success
} else {
throw e;
}
} Prevention
- Decide explicitly whether each copy may overwrite; only pass COPYFILE_EXCL when it may not
- Make install/bootstrap scripts idempotent by treating 'destination exists' as success
- Match the error by message prefix under Deno - the polyfill throws a plain Error without code
When it happens
Trigger: fs.copyFileSync(src, dst, fs.constants.COPYFILE_EXCL) where dst already exists - commonly from a previous run of the same script that partially completed.
Common situations: Idempotent install/bootstrap scripts re-run after partial completion; backup routines protecting existing archives; concurrent processes racing to create the same destination file.
Related errors
- ERR_MISSING_ARGS
- No callback function supplied
- ERR_INVALID_ARG_TYPE
- invalid ${name}, must not be infinity or NaN
- ERR_INVALID_ARG_VALUE
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/e24952ac0ff038db.
Report an issue: GitHub.