mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Password must be a string

Error message

Password must be a string

What it means

Thrown by passwordDigest (scram.ts:223) when the password passed to it is not a string. The SCRAM-SHA-1 MD5 digest requires a string password; a non-string password (undefined, number, object) cannot be hashed. Raised as MongoInvalidArgumentError. This is an internal type guard; credential parsing normally guarantees a string password before reaching SCRAM.

Solutions

  1. Ensure password is a non-empty string when constructing credentials
  2. If using the internal API, coerce password to string before it reaches SCRAM
  3. Prefer SCRAM-SHA-256 which routes through saslprep instead of passwordDigest
  4. Report a driver bug if reached via the public API

Example fix

// before
const credentials = { username: 'u', password: undefined, mechanism: 'SCRAM-SHA-1' };

// after
const credentials = { username: 'u', password: 'correct-horse', mechanism: 'SCRAM-SHA-1' };
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof clientOptions.auth?.password !== 'string') {
  throw new TypeError('auth.password must be a string');
}

Type guard

function isStringPassword(auth: { password?: unknown }): auth is { password: string } {
  return typeof auth.password === 'string' && auth.password.length > 0;
}

Try / catch

try {
  await client.connect();
} catch (err) {
  if (err instanceof MongoInvalidArgumentError && /Password must be a string/.test(err.message)) {
    // supply a valid string password and retry
  } else throw err;
}

Prevention

When it happens

Trigger: passwordDigest invoked on the SCRAM-SHA-1 path with a password that is not a string. Reachable only if credentials.password is undefined/null/non-string when SCRAM-SHA-1 runs, bypassing normal credential parsing.

Common situations: A driver regression or fork where credentials.password is not coerced to a string. Programmatic MongoCredentials construction with a non-string password. Note: an empty string password throws a separate 'Password cannot be empty' error just below.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/b2914ba2d36e8d57. Report an issue: GitHub.

Appendix: source

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

function parsePayload(payload: Binary) {
  const payloadStr = ByteUtils.toUTF8(payload.buffer, 0, payload.position, false);
  const dict: Document = {};
  const parts = payloadStr.split(',');
  for (let i = 0; i < parts.length; i++) {
    const valueParts = (parts[i].match(/^([^=]*)=(.*)$/) ?? []).slice(1);
    dict[valueParts[0]] = valueParts[1];
  }
  return dict;
}

function passwordDigest(username: string, password: string) {
  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
      }
    );

View on GitHub (pinned to dce7939f86)