Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion packages/cubejs-postgres-driver/src/PostgresDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class PostgresDriver<Config extends PostgresDriverConfiguration = Postgre
...config
});
this.pool.on('error', (err) => {
console.log(`Unexpected error on idle client: ${err.stack || err}`); // TODO
this.databasePoolError(err);
});
this.config = <Partial<Config>>{
...this.getInitialConfiguration(dataSource),
Expand Down Expand Up @@ -298,6 +298,13 @@ export class PostgresDriver<Config extends PostgresDriverConfiguration = Postgre

const conn = await this.pool.connect();

// Attach error handler to the client to prevent unhandled error events
// from crashing the process when connections are terminated unexpectedly.
// See: https://github.com/brianc/node-postgres/issues/2112
conn.on('error', (err) => {
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error listener is being attached each time a connection is acquired from the pool, but it's never removed. When connections are reused from the pool, this will result in multiple identical error listeners accumulating on the same connection object, causing a memory leak. Consider using conn.once('error', ...) instead of conn.on('error', ...) to ensure the listener is automatically removed after the first error, or explicitly remove the listener in the finally block or release callback.

Suggested change
conn.on('error', (err) => {
conn.once('error', (err) => {

Copilot uses AI. Check for mistakes.
this.databasePoolError(err);
});

try {
await this.prepareConnection(conn);

Expand Down Expand Up @@ -342,6 +349,13 @@ export class PostgresDriver<Config extends PostgresDriverConfiguration = Postgre

const conn = await this.pool.connect();

// Attach error handler to the client to prevent unhandled error events
// from crashing the process when connections are terminated unexpectedly.
// See: https://github.com/brianc/node-postgres/issues/2112
conn.on('error', (err) => {
this.databasePoolError(err);
});
Comment on lines +355 to +357
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error listener is being attached each time a connection is acquired from the pool, but it's never removed. When connections are reused from the pool, this will result in multiple identical error listeners accumulating on the same connection object, causing a memory leak. Consider using conn.once('error', ...) instead of conn.on('error', ...) to ensure the listener is automatically removed after the first error, or explicitly remove the listener in the finally block.

Copilot uses AI. Check for mistakes.

try {
await this.prepareConnection(conn);

Expand Down
9 changes: 8 additions & 1 deletion packages/cubejs-questdb-driver/src/QuestDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export class QuestDriver<Config extends QuestDriverConfiguration = QuestDriverCo
...config
});
this.pool.on('error', (err) => {
console.log(`Unexpected error on idle client: ${err.stack || err}`);
this.databasePoolError(err);
});
this.config = <Partial<Config>>{
...this.getInitialConfiguration(),
Expand Down Expand Up @@ -144,6 +144,13 @@ export class QuestDriver<Config extends QuestDriverConfiguration = QuestDriverCo
private async queryResponse(query: string, values: unknown[]) {
const conn = await this.pool.connect();

// Attach error handler to the client to prevent unhandled error events
// from crashing the process when connections are terminated unexpectedly.
// See: https://github.com/brianc/node-postgres/issues/2112
conn.on('error', (err) => {
Copy link

Copilot AI Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error listener is being attached each time a connection is acquired from the pool, but it's never removed. When connections are reused from the pool, this will result in multiple identical error listeners accumulating on the same connection object, causing a memory leak. Consider using conn.once('error', ...) instead of conn.on('error', ...) to ensure the listener is automatically removed after the first error, or explicitly remove the listener in the finally block.

Suggested change
conn.on('error', (err) => {
conn.once('error', (err) => {

Copilot uses AI. Check for mistakes.
this.databasePoolError(err);
});

try {
const res = await conn.query({
text: query,
Expand Down
Loading