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

create and createNew make Deno.open create the file, which only makes sense on a writable or appendable handle. Opening with create flags but no write/append would create a file you could not write to, so Deno rejects the combination before touching the filesystem.

Solutions

  1. Add write: true (or append: true) whenever create/createNew is used
  2. For create-and-write semantics use the shorthand Deno.create(path) (read+write+create+truncate)
  3. For touch-like behavior, Deno.createSync(path) then immediately close

Example fix

// before
const f = await Deno.open(path, { create: true });

// after
const f = await Deno.open(path, { read: true, write: true, create: 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;
}

const f = await Deno.open(path, normalizeOpenOptions(opts));

Prevention

When it happens

Trigger: Deno.open(path, { create: true }); Deno.open(path, { createNew: true, read: true }) with no write/append; 'ensure the file exists' logic implemented as open-with-create.

Common situations: Touch-like existence checks; porting Node fs.open mappings; copy-pasted option objects where the write line was dropped.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/745f9e7c17dad73e. Report an issue: GitHub.

Appendix: 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 9ad36f7a2c)