sidorares/node-mysql2 · critical · Error

Server requests authentication using unknown plugin

Error message

Server requests authentication using unknown plugin ${pluginName}. See ${'TODO: add plugins doco here'} on how to configure or author authentication plugins.

What it means

In authSwitchRequest (lib/commands/auth_switch.js:97-102), the server's AuthSwitchRequest names a plugin that is neither one of the four built-ins (caching_sha2_password, sha256_password, mysql_native_password, mysql_clear_password) nor present in connection.config.authPlugins. The driver cannot proceed without an implementation of that plugin, so it throws fatal. The message still references a TODO doc URL that has not been filled in.

Solutions

  1. Provide a custom plugin implementation via createConnection({ authPlugins: { '<pluginName>': pluginFactory } }).
  2. Change the server account to a supported plugin: ALTER USER ... IDENTIFIED WITH 'mysql_native_password' (or caching_sha2_password) BY 'pw'.
  3. Upgrade mysql2 — newer releases add built-in support for more plugins.
  4. For MariaDB ed25519, install/use a compatible client or implement the authPlugins callback.

Example fix

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

// after: supply the missing plugin factory
const conn = mysql.createConnection({
  host, user, password,
  authPlugins: { ed25519: ed25519PluginFactory },
});
Defensive patterns

Strategy: validation

Validate before calling

const knownPlugins = ['caching_sha2_password','sha256_password','mysql_native_password','mysql_clear_password'];
if (!knownPlugins.includes(serverPlugin) && !(config.authPlugins || {})[serverPlugin]) {
  throw new Error(`Provide authPlugins.${serverPlugin} or ALTER USER to a supported plugin.`);
}

Type guard

const isKnownPlugin = (name, authPlugins = {}) =>
  ['caching_sha2_password','sha256_password','mysql_native_password','mysql_clear_password'].includes(name) || Object.prototype.hasOwnProperty.call(authPlugins, name);

Try / catch

try { await mysql.createConnection(cfg); } catch (e) { if (/unknown plugin/.test(e.message)) { /* add authPlugins entry or ALTER USER */ } throw e; }

Prevention

When it happens

Trigger: MySQL server account pinned to an auth plugin the client does not ship (e.g. ed25519 on MariaDB, or an enterprise PAM/LDAP plugin); a MariaDB server defaulting to a plugin not in the standard set; connecting to an AWS Aurora or ProxySQL instance that advertises a custom plugin name.

Common situations: MariaDB with unix_socket or ed25519; a hardened server using auth_pam; newer server advertising a plugin the older mysql2 client predates.

Understand the failure class

Related errors


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

Appendix: source

Thrown at lib/commands/auth_switch.js:99

      );
    if (!hasCustomPlugin && !connection.config.enableCleartextPlugin) {
      const err = new Error(
        'Server requested authentication using mysql_clear_password, ' +
          'which sends the password in plaintext over the network and is ' +
          'disabled by default. To enable it, set the `enableCleartextPlugin` ' +
          'option to `true` in your connection configuration, or provide a ' +
          'custom `mysql_clear_password` auth plugin via the `authPlugins` ' +
          'option. Only use this over a secure connection (TLS/SSL).'
      );
      err.code = 'MYSQL_CLEAR_PASSWORD_NOT_ENABLED';
      err.fatal = true;
      throw err;
    }
  }

  const authPlugin = getAuthPlugin(pluginName, connection);
  if (!authPlugin) {
    throw new Error(
      `Server requests authentication using unknown plugin ${pluginName}. See ${'TODO: add plugins doco here'} on how to configure or author authentication plugins.`
    );
  }
  connection._authPlugin = authPlugin({ connection, command });
  Promise.resolve(connection._authPlugin(pluginData))
    .then((data) => {
      if (data) {
        connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());
      }
    })
    .catch((err) => {
      authSwitchPluginError(err, command);
    });
}

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

View on GitHub (pinned to 8b1f829d37)