sidorares/node-mysql2 · critical · Error

Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugi

Error message

Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_TOKEN_SENT state.

What it means

Thrown by the caching_sha2_password auth plugin when, after the client sent its scrambled password token (STATE_TOKEN_SENT), the server replies with an AuthMoreData packet whose first byte is neither 0x03 (fast-auth success) nor 0x04 (perform full authentication). The plugin's state machine at lib/auth_plugins/caching_sha2_password.js:67-93 only recognizes those two bytes, so any other leading byte is treated as a protocol violation. It almost always indicates a malformed or intercepted auth exchange rather than a normal client misconfiguration.

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 8b1f829d37)

Solutions

  1. Verify the MySQL server version and that no proxy/pooler is intercepting the auth handshake (connect directly to the mysqld port).
  2. Force a clear protocol by either enabling SSL (set config.ssl) or downgrading the server account to mysql_native_password (ALTER USER ... IDENTIFIED WITH mysql_native_password) to bypass caching_sha2_password entirely.
  3. If a proxy is required, upgrade or reconfigure it to be transparent for the auth phase, or pin the connection to a single backend node.
  4. Update mysql2 to the latest release, since auth-state-machine fixes land frequently.

Example fix

// before: plaintext connection through an intercepting proxy
const conn = mysql.createConnection({ host: 'proxy', user: 'u', password: 'p' });

// after: TLS so the proxy cannot rewrite the auth exchange
const conn = mysql.createConnection({ host: 'db', user: 'u', password: 'p', ssl: { rejectUnauthorized: true } });
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const conn = await mysql.createConnection({ host, user, password, ssl: { rejectUnauthorized: true } });
} catch (e) {
  if (/caching_sha2_password.*STATE_TOKEN_SENT/.test(e.message)) {
    // auth exchange tampered/proxied: bypass proxy or enable TLS
  }
  throw e;
}

Prevention

When it happens

Trigger: Connecting to a MySQL 8.x server whose default auth plugin is caching_sha2_password, where an intermediary (proxy, man-in-the-middle, buggy connection pooler like a stale PgBouncer-style proxy) rewrites or truncates the AuthMoreData packet. Also reproducible when the server's cached auth state is corrupted, or when the connection is half-closed and stale bytes are read as an auth packet.

Common situations: Upgrading a MySQL server from 5.7 (mysql_native_password) to 8.x (caching_sha2_password) behind a proxy that does not understand the new plugin's multi-step flow; using a load balancer that buffers/rewrites auth packets; a network device corrupting the SSL handshake so the client misreads encrypted bytes as a cleartext AuthMoreData packet.

Related errors


AI-assisted analysis of sidorares/node-mysql2@8b1f829d37 (2026-08-11). Data as JSON: /api/errors/256b1b61a595aef5. Report an issue: GitHub.