sidorares/node-mysql2 · error · TypeError
HandshakeResponse authToken must be a Buffer when provided
Error message
HandshakeResponse authToken must be a Buffer when provided
What it means
HandshakeResponse constructor (lib/packets/handshake_response.js:23-32) accepts an optional pre-computed authToken for fast-path auth optimization, but when BOTH authToken and authPluginName are provided it requires authToken to be a Buffer (because it is written as raw bytes at serializeResponse line 80-88). Passing any non-Buffer throws TypeError to fail fast before wire serialization.
Solutions
- Provide authToken as a Buffer: authToken: Buffer.from(token, ...).
- If you only have a password, omit authToken/authPluginName and let the constructor fall back to mysql_native_password token calculation (line 40-58).
- Validate Buffer.isBuffer(authToken) before constructing HandshakeResponse.
Example fix
// before
new HandshakeResponse({ ..., authToken: 'abc', authPluginName: 'x' });
// after
new HandshakeResponse({ ..., authToken: Buffer.from('abc'), authPluginName: 'x' }); Defensive patterns
Strategy: type-guard
Validate before calling
if (authToken !== undefined && !Buffer.isBuffer(authToken)) {
throw new TypeError('authToken must be a Buffer');
} Type guard
const isAuthTokenBuffer = (v) => v === undefined || Buffer.isBuffer(v);
Prevention
- Always wrap token computation in Buffer.from(...).
- Type the HandshakeResponse options strictly when integrating custom auth.
When it happens
Trigger: Constructing HandshakeResponse manually with authToken as a string or number; an auth-plugin integration returning a string token where a Buffer is required; a custom handshake wrapper that computes a token but forgets Buffer.from(...).
Common situations: Custom auth plugin development; monkey-patching the initial handshake; integration code that confuses the legacy password-string path with the pre-computed-token path.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- HandshakeResponse authPluginName must be a string when…
- Bind parameters must not contain undefined
- "database" connection config property must be a string
- "user" connection config property must be a string
- "user" connection config property must be a string
AI-assisted analysis of sidorares/node-mysql2@8b1f829d37 (2026-08-11).
Data as JSON: /api/errors/86ad687b96bab6d8.
Report an issue: GitHub.
Appendix: source
Thrown at lib/packets/handshake_response.js:29
this.user = handshake.user || '';
this.database = handshake.database || '';
this.password = handshake.password || '';
this.passwordSha1 = handshake.passwordSha1;
this.authPluginData1 = handshake.authPluginData1;
this.authPluginData2 = handshake.authPluginData2;
this.compress = handshake.compress;
this.clientFlags = handshake.flags;
this.mariadbExtendedClientFlags = handshake.mariadbExtendedClientFlags || 0;
// Accept pre-calculated authToken and authPluginName from caller
// This allows the caller to optimize by using the server's preferred auth method
if (
handshake.authToken !== undefined &&
handshake.authPluginName !== undefined
) {
// Validate types to fail fast with clear errors
if (!Buffer.isBuffer(handshake.authToken)) {
throw new TypeError(
'HandshakeResponse authToken must be a Buffer when provided'
);
}
if (typeof handshake.authPluginName !== 'string') {
throw new TypeError(
'HandshakeResponse authPluginName must be a string when provided'
);
}
this.authToken = handshake.authToken;
this.authPluginName = handshake.authPluginName;
} else {
// Fallback to legacy behavior: calculate mysql_native_password token
// TODO: pre-4.1 auth support
let authToken;
if (this.passwordSha1) {
authToken = auth41.calculateTokenFromPasswordSha(
this.passwordSha1,
this.authPluginData1,View on GitHub (pinned to 8b1f829d37)