From 2c9c9f872aac896d980a8284ee6e8a3dab8d6d73 Mon Sep 17 00:00:00 2001 From: Karen Chen <64801825+karenc-bq@users.noreply.github.com> Date: Tue, 6 Jan 2026 09:10:47 -0800 Subject: [PATCH] fix: mysql's event listeners should be removed from `clientWrapper.client.connection` not `clientWrapper.client` and ensure the same error listener is not attached multiple times --- mysql/lib/mysql_error_handler.ts | 21 ++++++++++++++------- pg/lib/abstract_pg_error_handler.ts | 11 +++++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mysql/lib/mysql_error_handler.ts b/mysql/lib/mysql_error_handler.ts index 69d23e1e0..45066735c 100644 --- a/mysql/lib/mysql_error_handler.ts +++ b/mysql/lib/mysql_error_handler.ts @@ -24,6 +24,8 @@ export class MySQLErrorHandler implements ErrorHandler { private unexpectedError: Error | null = null; protected static readonly SYNTAX_ERROR_CODES = ["42000", "42S02"]; protected static readonly SYNTAX_ERROR_MESSAGE = "You have an error in your SQL syntax"; + protected isNoOpListenerAttached = false; + protected isTrackingListenerAttached = false; protected noOpListener(error: any) { // Ignore the received error. @@ -80,20 +82,24 @@ export class MySQLErrorHandler implements ErrorHandler { } attachErrorListener(clientWrapper: ClientWrapper | undefined): void { - if (!clientWrapper || !clientWrapper.client) { + if (!clientWrapper || !clientWrapper.client || this.isTrackingListenerAttached) { return; } this.unexpectedError = null; - clientWrapper.client.removeListener("error", this.noOpListener); - clientWrapper.client.on("error", this.trackingListener); + clientWrapper.client.connection.removeListener("error", this.noOpListener); + this.isNoOpListenerAttached = false; + clientWrapper.client.connection.on("error", this.trackingListener); + this.isTrackingListenerAttached = true; } attachNoOpErrorListener(clientWrapper: ClientWrapper | undefined): void { - if (!clientWrapper || !clientWrapper.client) { + if (!clientWrapper || !clientWrapper.client || this.isNoOpListenerAttached) { return; } - clientWrapper.client.removeListener("error", this.trackingListener); - clientWrapper.client.on("error", this.noOpListener); + clientWrapper.client.connection.removeListener("error", this.trackingListener); + this.isTrackingListenerAttached = false; + clientWrapper.client.connection.on("error", this.noOpListener); + this.isNoOpListenerAttached = true; } removeErrorListener(clientWrapper: ClientWrapper | undefined): void { @@ -101,6 +107,7 @@ export class MySQLErrorHandler implements ErrorHandler { return; } - clientWrapper.client.removeListener("error", this.trackingListener); + clientWrapper.client.connection.removeListener("error", this.trackingListener); + this.isTrackingListenerAttached = false; } } diff --git a/pg/lib/abstract_pg_error_handler.ts b/pg/lib/abstract_pg_error_handler.ts index cefa2b7db..9a5799c00 100644 --- a/pg/lib/abstract_pg_error_handler.ts +++ b/pg/lib/abstract_pg_error_handler.ts @@ -24,6 +24,8 @@ export abstract class AbstractPgErrorHandler implements ErrorHandler { protected unexpectedError: Error | null = null; protected static readonly SYNTAX_ERROR_CODE = "42601"; protected static readonly SYNTAX_ERROR_MESSAGE = "syntax error"; + protected isNoOpListenerAttached = false; + protected isTrackingListenerAttached = false; abstract getNetworkErrors(): string[]; @@ -84,20 +86,24 @@ export abstract class AbstractPgErrorHandler implements ErrorHandler { } attachErrorListener(clientWrapper: ClientWrapper | undefined): void { - if (!clientWrapper || !clientWrapper.client) { + if (!clientWrapper || !clientWrapper.client || this.isTrackingListenerAttached) { return; } this.unexpectedError = null; clientWrapper.client.removeListener("error", this.noOpListener); + this.isNoOpListenerAttached = false; clientWrapper.client.on("error", this.trackingListener); + this.isTrackingListenerAttached = true; } attachNoOpErrorListener(clientWrapper: ClientWrapper | undefined): void { - if (!clientWrapper || !clientWrapper.client) { + if (!clientWrapper || !clientWrapper.client || this.isNoOpListenerAttached) { return; } clientWrapper.client.removeListener("error", this.trackingListener); + this.isTrackingListenerAttached = false; clientWrapper.client.on("error", this.noOpListener); + this.isNoOpListenerAttached = true; } removeErrorListener(clientWrapper: ClientWrapper | undefined): void { @@ -106,5 +112,6 @@ export abstract class AbstractPgErrorHandler implements ErrorHandler { } clientWrapper.client.removeListener("error", this.trackingListener); + this.isTrackingListenerAttached = false; } }