denoland/deno · error · Error
'create' or 'createNew' options require 'write' or 'append'
Error message
'create' or 'createNew' options require 'write' or 'append' to be true
What it means
Final rule of checkOpenOptions for Deno.open/openSync: create/createNew only make sense when the file will also be written or appended to. Opening with create: true (or createNew: true) but neither write nor append would create a file that can never receive bytes, so a plain Error is thrown. This mirrors Node's validation for the same flag combinations.
Source
Thrown at ext/fs/30_fs.js:817
).length === 0
) {
throw new Error(
"'options' requires at least one option to be true",
);
}
if (options.truncate && !options.write) {
throw new Error(
"'truncate' option requires 'write' to be true",
);
}
const createOrCreateNewWithoutWriteOrAppend =
(options.create || options.createNew) &&
!(options.write || options.append);
if (createOrCreateNewWithoutWriteOrAppend) {
throw new Error(
"'create' or 'createNew' options require 'write' or 'append' to be true",
);
}
}
function readFileSync(path) {
return op_fs_read_file_sync(pathFromURL(path));
}
async function readFile(path, options) {
let cancelRid;
let abortHandler;
if (options?.signal) {
options.signal.throwIfAborted();
cancelRid = createCancelHandle();
abortHandler = () => core.tryClose(cancelRid);
options.signal[abortSignal.add](abortHandler);
}View on GitHub (pinned to 89f33cbef2)
Solutions
- Pair create with write: { create: true, write: true } (or append: true)
- For touch-like creation with content, use Deno.writeTextFile with create: true
- For Node-'w' behavior use { write: true, create: true, truncate: true }; for fail-if-exists use createNew
Example fix
// before
await Deno.open("/tmp/x", { create: true }); // Error
// after
await Deno.open("/tmp/x", { create: true, write: true }); Defensive patterns
Strategy: validation
Validate before calling
function normalizeOpenOptions(o) {
if ((o.create || o.createNew) && !(o.write || o.append)) o = { ...o, write: true };
return o;
}
await Deno.open(path, normalizeOpenOptions(options)); Type guard
function areCreateOptionsValid(o: {
create?: boolean;
createNew?: boolean;
write?: boolean;
append?: boolean;
}): boolean {
return !((o.create || o.createNew) && !(o.write || o.append));
} Try / catch
try {
file = await Deno.open(path, options);
} catch (err) {
if (err instanceof Error && err.message === "'create' or 'createNew' options require 'write' or 'append' to be true") {
file = await Deno.open(path, { ...options, write: true });
} else throw err;
} Prevention
- Remember create/createNew alone do nothing valid; add write or append
- For touch-like creation use Deno.writeTextFile(path, "", { create: true })
- Centralize flag mapping from other runtimes instead of hand-building options per call
When it happens
Trigger: Deno.open(path, { create: true }) or Deno.openSync(path, { createNew: true }) without write: true or append: true.
Common situations: Expecting create to work like touch; porting Node flag 'wx'/'ax' partially; constructing options from conditionals where the write flag is dropped when a file already exists.
Related errors
- 'options' requires at least one option to be true
- 'truncate' option requires 'write' to be true
- 'Deno.FsFile' cannot be constructed, use 'Deno.open()' or 'D
- A file exists at the destination: ${destStr}
- ERR_MISSING_ARGS
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/745f9e7c17dad73e.
Report an issue: GitHub.