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 accepts an optional pre-calculated `authToken` plus `authPluginName` (both must be provided together to take the optimised path). If both keys are present but `authToken` is not a Buffer, it throws at construction. This is an internal/advanced API used to short-circuit the initial handshake token; normal callers never set these fields.
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 5ebe8903d6)
Solutions
- Pass authToken as a Buffer: `new HandshakeResponse({ ..., authToken: Buffer.from(token), authPluginName })`.
- If you do not need the optimised path, omit both authToken and authPluginName and let HandshakeResponse compute the token.
Example fix
// before
new HandshakeResponse({ ..., authToken: 'raw', authPluginName: 'x' });
// after
new HandshakeResponse({ ..., authToken: Buffer.from('raw'), authPluginName: 'x' }); Defensive patterns
Strategy: type-guard
Validate before calling
function buildHandshakeOpts(opts) {
if (opts.authToken !== undefined) {
if (!Buffer.isBuffer(opts.authToken)) throw new TypeError('authToken must be a Buffer');
if (typeof opts.authPluginName !== 'string') throw new TypeError('authPluginName must be a string');
}
return opts;
} Type guard
function isValidAuthToken(token) {
return token == null || Buffer.isBuffer(token);
} Prevention
- Only set authToken/authPluginName if you compute them yourself; otherwise omit both.
- Always wrap tokens with Buffer.from(...) before passing.
- Keep HandshakeResponse construction in internal/test code only.
When it happens
Trigger: Constructing a HandshakeResponse packet directly (or via a custom auth flow) and passing `authToken` as a string or number while also passing `authPluginName`. Application code using the standard connection API will not hit this because the library computes the token itself.
Common situations: Advanced users building a custom handshake or mocking the packet in tests; a fork/patch that passes a string token by mistake.
Related errors
- HandshakeResponse authPluginName must be a string when provi
- Unexpected data in AuthMoreData packet received by caching_s
- Unexpected data in AuthMoreData packet received by sha256_pa
- Invalid AuthMoreData packet received by caching_sha2_passwor
- Unexpected data in AuthMoreData packet received by caching_s
AI-assisted analysis of sidorares/node-mysql2@5ebe8903d6 (2026-08-03).
Data as JSON: /data/errors/86ad687b96bab6d8.json.
Report an issue: GitHub.