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) when the username passed to it is not a string. passwordDigest builds the SCRAM-SHA-1 MD5 digest from `${username}:mongo:${password}`, so a non-string username (undefined, number, object) cannot be hashed. Raised as MongoInvalidArgumentError. This guard is internal; the public API normalizes credentials to strings upstream.
Solutions
- Ensure username is a string when constructing credentials (the public API does this for you)
- If using the internal API, coerce username to string before it reaches SCRAM
- Prefer SCRAM-SHA-256 which uses saslprep instead of passwordDigest
- Report a driver bug if reached via the public API
Example fix
// before
const credentials = { username: undefined, password: 'x', mechanism: 'SCRAM-SHA-1' };
// after
const credentials = { username: 'appUser', password: 'x', mechanism: 'SCRAM-SHA-1' }; Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof clientOptions.auth?.username !== 'string') {
throw new TypeError('auth.username must be a string');
} Type guard
function isStringUsername(auth: { username?: unknown }): auth is { username: string } {
return typeof auth.username === 'string';
} Try / catch
try {
await client.connect();
} catch (err) {
if (err instanceof MongoInvalidArgumentError && /Username must be a string/.test(err.message)) {
// coerce/fix username and retry
} else throw err;
} Prevention
- Always pass string credentials via the public MongoClient options
- Validate auth.username is a string at config-load time
- Prefer SCRAM-SHA-256, which does not route through passwordDigest
When it happens
Trigger: passwordDigest is invoked (only on the SCRAM-SHA-1 path, scram.ts:136) with a username that is not a string. Reachable if credentials.username is undefined/null/non-string when SCRAM-SHA-1 runs, which the credential-parsing layer normally prevents.
Common situations: A driver regression or fork where credentials.username is not coerced to a string before SCRAM-SHA-1 auth. Programmatic construction of MongoCredentials with a non-string username. A test that bypasses credential parsing.
Related errors
- Password must be a string
- AuthContext must contain a valid nonce property
- No AuthProvider for defined.
- Unable to continue SCRAM without valid nonce
- Auth mechanism SCRAM-SHA-1 is not supported in FIPS mode
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/c3f2effd2fe1d3dd.
Report an issue: GitHub.
Appendix: 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 dce7939f86)