denoland/deno · error · ConstructCallRequiredError

ERR_CONSTRUCT_CALL_REQUIRED

ERR_CONSTRUCT_CALL_REQUIRED

Error message

Cannot call constructor without `new`

What it means

DatabaseSync is an ES5-style wrapper function around the native op class so that it can validate the call form. Invoking it as a plain function (`DatabaseSync(':memory:')`) skips construction, so the wrapper checks `new.target === undefined` and throws ERR_CONSTRUCT_CALL_REQUIRED ('Cannot call constructor without `new`') before any native code runs.

Source

Thrown at ext/node/polyfills/sqlite.ts:160

    typeof parsedPath === "undefined" ||
    StringPrototypeIncludes(parsedPath, "\0")
  ) {
    throw new InvalidArgTypeError(
      'The "path" argument must be a string, Uint8Array, or URL without null bytes.',
    );
  }

  return parsedPath;
};

// Using ES5 class allows custom error to be thrown
// when called without `new`.
function DatabaseSync(
  path,
  options,
) {
  if (new.target === undefined) {
    throw new ConstructCallRequiredError();
  }
  return ReflectConstruct(
    DatabaseSyncOp,
    [parsePath(path), options],
    new.target,
  );
}
ObjectSetPrototypeOf(DatabaseSync.prototype, DatabaseSyncOp.prototype);
ObjectSetPrototypeOf(DatabaseSync, DatabaseSyncOp);

function validateBackupOptions(options) {
  if (options === undefined) {
    return;
  }
  if (typeof options !== "object" || options === null) {
    throw new InvalidArgTypeError(
      'The "options" argument must be an object.',
    );

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Always construct with `new`: `new DatabaseSync(path)`
  2. Wrap in an explicit factory that forwards with new: `const connect = (path) => new DatabaseSync(path)`
  3. When passing constructors as callbacks, use arrow wrappers: `.map((p) => new DatabaseSync(p))`

Example fix

// before
const db = DatabaseSync('app.db');
// ERR_CONSTRUCT_CALL_REQUIRED

// after
const db = new DatabaseSync('app.db');
// or a factory wrapper
const connect = (path) => new DatabaseSync(path);
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const db = DatabaseSync(path); // forgot `new`
} catch (e) {
  if (e.code === 'ERR_CONSTRUCT_CALL_REQUIRED') {
    throw new Error('DatabaseSync must be called with `new`');
  }
  throw e;
}

Prevention

When it happens

Trigger: `const db = DatabaseSync('db.sqlite')` without `new`; aliasing the class (`const connect = DatabaseSync; connect(path)`) or passing it as a callback (`.map(DatabaseSync)`), which loses construct semantics.

Common situations: Porting better-sqlite3 factory-style wrappers (`connect(path)`); bundled/minified code that drops `new`; calling via `.call(null, path)`.

Related errors


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