sidorares/node-mysql2 · error · Error

Invalid AuthMoreData packet received by caching_sha2_passwor

Error message

Invalid AuthMoreData packet received by caching_sha2_password plugin in STATE_TOKEN_SENT state.

What it means

During caching_sha2_password authentication, after the client sends its scramble-based token (STATE_TOKEN_SENT), the server is expected to reply with either a fast-auth-success byte (0x03) or a perform-full-authentication byte (0x04). If the AuthMoreData packet contains any other leading byte, the plugin cannot interpret the server's intent and throws this error. This is a MySQL wire-protocol contract violation — the server sent something the plugin does not recognise for this handshake phase.

Source

Thrown at lib/auth_plugins/caching_sha2_password.js:91

          if (PERFORM_FULL_AUTHENTICATION_PACKET.equals(data)) {
            const isSecureConnection =
              typeof pluginOptions.overrideIsSecure === 'undefined'
                ? connection.config.ssl || connection.config.socketPath
                : pluginOptions.overrideIsSecure;
            if (isSecureConnection) {
              state = STATE_FINAL;
              return Buffer.from(`${password}\0`, 'utf8');
            }

            // if client provides key we can save one extra roundrip on first connection
            if (pluginOptions.serverPublicKey) {
              return authWithKey(pluginOptions.serverPublicKey);
            }

            state = STATE_WAIT_SERVER_KEY;
            return REQUEST_SERVER_KEY_PACKET;
          }
          throw new Error(
            `Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_TOKEN_SENT state.`
          );
        case STATE_WAIT_SERVER_KEY:
          if (pluginOptions.onServerPublicKey) {
            pluginOptions.onServerPublicKey(data);
          }
          return authWithKey(data);
        case STATE_FINAL:
          throw new Error(
            `Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
          );
      }

      throw new Error(
        `Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
      );
    };
  };

View on GitHub (pinned to 5ebe8903d6)

Solutions

  1. Enable SSL/TLS on the connection (set ssl options) so the auth exchange is encrypted and less susceptible to middleware tampering, and so caching_sha2_password can use the secure-connection fast path.
  2. Verify the MySQL server version and that it genuinely supports caching_sha2_password; if it is a proxy or fork, test a direct connection to the real mysqld to isolate the intermediary.
  3. Upgrade mysql2 to the latest release, as protocol-handling fixes land frequently.
  4. If you control the server, set the user's plugin to mysql_native_password as a workaround (ALTER USER ... IDENTIFIED WITH mysql_native_password).
  5. Inspect network/MTU settings and proxy configuration for packet corruption or rewriting.

Example fix

// before
const conn = mysql.createConnection({ host, user, password });

// after (force TLS so the auth handshake is protected)
const conn = mysql.createConnection({
  host,
  user,
  password,
  ssl: { rejectUnauthorized: true },
});
Defensive patterns

Strategy: try-catch

Validate before calling

// No caller-side validation can predict a malformed server packet.
// Validate reachability/compatibility instead:
function preflightAuth(host, port) {
  // ensure server is reachable and is a real MySQL 8+ before relying on caching_sha2_password
  return checkPortOpen(host, port) && checkServerVersion(host, port);
}

Try / catch

try {
  const conn = await mysql.createConnection({ host, user, password, ssl: { rejectUnauthorized: true } });
} catch (err) {
  if (/Invalid AuthMoreData packet.*caching_sha2_password/.test(err.message)) {
    // log and retry with mysql_native_password account or via a different route
  } else throw err;
}

Prevention

When it happens

Trigger: Connecting to a MySQL 8+ server that uses caching_sha2_password (the 8.0+ default) where the server's AuthMoreData reply starts with a byte that is neither 0x03 nor 0x04 during the second leg of the handshake. Typically caused by a truncated/corrupted packet on the TCP stream, an incompatible or buggy server/proxy, or a man-in-the-middle altering the auth exchange.

Common situations: A buggy or non-conformant MySQL-compatible proxy (e.g. an older ProxySQL, a custom proxy, or a load balancer doing L7 inspection) rewriting auth packets; a flaky network dropping bytes; connecting to a server whose authentication plugin behaviour diverges from upstream MySQL (some forks/older MariaDB builds); TCP packet corruption from MTU/MSS mismatch.

Related errors


AI-assisted analysis of sidorares/node-mysql2@5ebe8903d6 (2026-08-03). Data as JSON: /data/errors/6265c5490d6852af.json. Report an issue: GitHub.