{"record":{"id":"d937c0fc42d79f8a","repo":"sidorares/node-mysql2","slug":"authpluginmoredata-received-but-no-auth-plugin-ins","errorCode":null,"errorMessage":"AuthPluginMoreData received but no auth plugin instance found","messagePattern":"AuthPluginMoreData received but no auth plugin instance found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/commands/auth_switch.js","lineNumber":131,"sourceCode":"}\n\nfunction authSwitchRequestMoreData(packet, connection, command) {\n  const { data } = Packets.AuthSwitchRequestMoreData.fromPacket(packet);\n\n  if (connection.config.authSwitchHandler) {\n    const legacySwitchHandler = connection.config.authSwitchHandler;\n    warnLegacyAuthSwitch();\n    legacySwitchHandler({ pluginData: data }, (err, data) => {\n      if (err) {\n        return authSwitchPluginError(err, command);\n      }\n      connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());\n    });\n    return;\n  }\n\n  if (!connection._authPlugin) {\n    throw new Error(\n      'AuthPluginMoreData received but no auth plugin instance found'\n    );\n  }\n  Promise.resolve(connection._authPlugin(data))\n    .then((data) => {\n      if (data) {\n        connection.writePacket(new Packets.AuthSwitchResponse(data).toPacket());\n      }\n    })\n    .catch((err) => {\n      authSwitchPluginError(err, command);\n    });\n}\n\nmodule.exports = {\n  authSwitchRequest,\n  authSwitchRequestMoreData,\n  getAuthPlugin,","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/sidorares/node-mysql2/blob/8b1f829d3706404ab372cf97bd77ebcf86578d97/lib/commands/auth_switch.js#L113-L149","documentation":"In authSwitchRequestMoreData (lib/commands/auth_switch.js:130-134), the driver received an AuthSwitchRequestMoreData packet (server continuing a multi-step auth exchange) but connection._authPlugin was never set — meaning the prior AuthSwitchRequest step did not instantiate a plugin. This is an internal sequencing error: the more-data packet arrived without the initial switch request having populated the plugin instance.","triggerScenarios":"A legacy authSwitchHandler is set (it returns early at line 118-128 and never sets _authPlugin, yet the server sends more-data that bypasses the legacy handler); a race where the connection is reset between the switch request and the more-data packet; a server that sends more-data without a preceding switch request.","commonSituations":"Using the deprecated authSwitchHandler callback API combined with a multi-roundtrip plugin; pooled connection reused mid-handshake; a proxy reordering auth packets.","solutions":["Migrate off the deprecated authSwitchHandler to the authPlugins config API, which keeps _authPlugin consistent across round-trips.","Ensure no two handshakes race on the same socket (avoid sharing connections across async contexts during connect).","Upgrade mysql2 and verify the server version; report if it persists on stock latest."],"exampleFix":"// before: deprecated handler that desyncs multi-roundtrip plugins\ncreateConnection({ authSwitchHandler: (data, cb) => cb(null, myData) });\n\n// after: plugin factory that handles all round-trips consistently\ncreateConnection({ authPlugins: { my_plugin: myPluginFactory } });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await conn.connect(); } catch (e) { if (/no auth plugin instance found/.test(e.message)) { /* stop using deprecated authSwitchHandler */ } throw e; }","preventionTips":["Replace authSwitchHandler with authPlugins before adding multi-roundtrip plugins.","Never share a socket between two concurrent connect attempts."],"tags":["authentication","auth-plugin","internal","deprecated-api"],"backgroundTag":null,"analyzedSha":"8b1f829d3706404ab372cf97bd77ebcf86578d97","analyzedAt":"2026-08-11T02:54:28.964Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}