sidorares/node-mysql2 · error · Error

AuthPluginMoreData received but no auth plugin instance foun

Error message

AuthPluginMoreData received but no auth plugin instance found

What it means

The server sent an AuthSwitchRequestMoreData packet but `connection._authPlugin` was never set — meaning no prior auth-switch request established a plugin instance to feed the data to. This is a protocol desync: the server jumped ahead in the conversation, or a previous plugin threw and left the connection in a half-initialised state.

Source

Thrown at lib/commands/auth_switch.js:131

}

function authSwitchRequestMoreData(packet, connection, command) {
  const { data } = Packets.AuthSwitchRequestMoreData.fromPacket(packet);

  if (connection.config.authSwitchHandler) {
    const legacySwitchHandler = connection.config.authSwitchHandler;
    warnLegacyAuthSwitch();
    legacySwitchHandler({ pluginData: data }, (err, data) => {
      if (err) {
        return authSwitchPluginError(err, command);
      }
      connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
    });
    return;
  }

  if (!connection._authPlugin) {
    throw new Error(
      'AuthPluginMoreData received but no auth plugin instance found'
    );
  }
  Promise.resolve(connection._authPlugin(data))
    .then((data) => {
      if (data) {
        connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
      }
    })
    .catch((err) => {
      authSwitchPluginError(err, command);
    });
}

module.exports = {
  authSwitchRequest,
  authSwitchRequestMoreData,
  getAuthPlugin,

View on GitHub (pinned to 5ebe8903d6)

Solutions

  1. Connect directly to mysqld, bypassing any proxy/pooler, to isolate the source.
  2. If using a custom `authPlugins` entry, ensure its factory returns a function and never throws during construction.
  3. Update/upgrade the proxy and mysql2.
  4. Enable TLS so intermediaries are less likely to interfere with the auth sequence.

Example fix

// before — custom plugin factory throws
authPlugins: { my_plugin: () => { throw new Error('bad'); } }

// after — factory returns a handler function
authPlugins: {
  my_plugin: (opts) => ({ connection }) => (data) => {
    return Buffer.from('response');
  },
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await mysql.createConnection(cfg);
} catch (err) {
  if (/AuthPluginMoreData received but no auth plugin instance/.test(err.message)) {
    // bypass proxy; verify custom authPlugins factory does not throw
  } else throw err;
}

Prevention

When it happens

Trigger: The server sends MoreData before (or without) a prior AuthSwitchRequest that would have instantiated the plugin; or the plugin factory threw during instantiation and `_authPlugin` stayed unset while packets kept arriving. Seen with proxies that reorder auth packets, or after a prior auth error was partially suppressed.

Common situations: A buggy proxy reordering/duplicating auth packets; a custom authPlugins factory that throws instead of returning a function; connecting through a pooler that hands off a half-authenticated socket.

Related errors


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