mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Username must be a string

Error message

Username must be a string

What it means

Thrown by passwordDigest() (scram.ts:219) as a MongoInvalidArgumentError when the username passed in is not a string. passwordDigest builds the MD5 of 'username:mongo:password' for SCRAM-SHA-1, so a non-string username (number, object, undefined) cannot be hashed. This guards an internal helper invoked during SCRAM-SHA-1 auth.

Source

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

  };

  await connection.command(ns(`${db}.$cmd`), retrySaslContinueCmd, undefined);
}

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',

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Ensure the username is a string - coerce with String(username) if loading from typed config
  2. Validate credentials shape before passing to MongoClient
  3. Use SCRAM-SHA-256 (default in modern MongoDB) where possible

Example fix

// before
const username = config.dbUser; // number 12345
// after
const username = String(config.dbUser);
Defensive patterns

Strategy: validation

Validate before calling

function assertStringUsername(username: unknown): asserts username is string {
  if (typeof username !== 'string') throw new TypeError('username must be a string');
}
assertStringUsername(config.dbUser);

Type guard

function isStringUsername(u: unknown): u is string {
  return typeof u === 'string';
}

Prevention

When it happens

Trigger: Credentials object whose username field is not a string (e.g. a number parsed from config without coercion, or undefined leaking through a loosely-typed credentials builder). Reachable if a MongoCredentials is constructed bypassing its normal validation.

Common situations: Numeric usernames in config systems that did not stringify; a credentials provider returning an object whose .username is undefined after a failed lookup; TS type-safety bypassed at runtime.

Related errors


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