mongodb/node-mongodb-native · error · MongoRuntimeError

Node.js crypto module is required for SCRAM-SHA-1 authentica

Error message

Node.js crypto module is required for SCRAM-SHA-1 authentication

What it means

Thrown by passwordDigest() (scram.ts:236) as a MongoRuntimeError when require('crypto') throws, meaning the Node.js crypto module is unavailable. SCRAM-SHA-1 authentication needs crypto to compute the MD5 password digest. In standard Node this is always present; the error indicates a stripped/custom runtime or sandboxing that removed built-in modules.

Source

Thrown at src/cmap/auth/scram.ts:236

  if (typeof username !== 'string') {
    throw new MongoInvalidArgumentError('Username must be a string');
  }

  if (typeof password !== 'string') {
    throw new MongoInvalidArgumentError('Password must be a string');
  }

  if (password.length === 0) {
    throw new MongoInvalidArgumentError('Password cannot be empty');
  }

  let nodeCrypto;
  try {
    // TODO: NODE-7424 - remove dependency on 'crypto' for SCRAM-SHA-1 authentication
    // eslint-disable-next-line @typescript-eslint/no-require-imports
    nodeCrypto = require('crypto');
  } catch (e) {
    throw new MongoRuntimeError(
      'Node.js crypto module is required for SCRAM-SHA-1 authentication',
      {
        cause: e
      }
    );
  }

  try {
    const md5 = nodeCrypto.createHash('md5');
    md5.update(`${username}:mongo:${password}`, 'utf8');
    return md5.digest('hex');
  } catch (err) {
    if (nodeCrypto.getFips()) {
      // This error is (slightly) more helpful than what comes from OpenSSL directly, e.g.
      // 'Error: error:060800C8:digital envelope routines:EVP_DigestInit_ex:disabled for FIPS'
      throw new Error('Auth mechanism SCRAM-SHA-1 is not supported in FIPS mode');
    }
    throw err;

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Run in a standard Node.js runtime where 'crypto' is a built-in
  2. Fix bundler config: set target: 'node' and do not mark 'crypto' as external in browser builds
  3. Switch to SCRAM-SHA-256 which uses WebCrypto (crypto.subtle) instead of the crypto module for the digest step where possible
  4. If sandboxing, allowlist the 'crypto' built-in module

Example fix

// webpack.config.js - before
target: 'web',
// after
target: 'node',
Defensive patterns

Strategy: type-guard

Validate before calling

function hasCryptoModule(): boolean {
  try { require('crypto'); return true; } catch { return false; }
}
if (!hasCryptoModule()) throw new Error('Node.js crypto module unavailable; cannot use SCRAM-SHA-1');

Type guard

declare const crypto: typeof import('crypto') | undefined;
function hasNodeCrypto(): crypto is typeof import('crypto') {
  try { require('crypto'); return true; } catch { return false; }
}

Try / catch

try {
  await client.connect();
} catch (e) {
  if (e instanceof MongoRuntimeError && /crypto module is required/i.test(e.message)) {
    // fix runtime/bundler, or switch authMechanism to SCRAM-SHA-256
  }
  throw e;
}

Prevention

When it happens

Trigger: Running in a constrained environment where the 'crypto' built-in has been removed or disabled (some edge runtimes, sandboxed eval, or bundler configs that externalize built-ins incorrectly). The require('crypto') call itself throws.

Common situations: Bundlers (webpack/esbuild) misconfigured to treat 'crypto' as external in a non-Node environment; running the driver in a non-Node runtime that lacks crypto; security policy stripping built-ins.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/f578c0ca7f4dded4.json. Report an issue: GitHub.