Skip to content

Uncatchable exception on idle in transcation timeout #1133

@k0nserv

Description

@k0nserv

Hello!

If you trigger a connection termination due to idle in transaction timeout postgres throws an error that is not catchable from the callsite.

Minimal repro:

const postgres = require("postgres");

const sql = postgres({
  host: process.env.PGHOST || "localhost",
  port: process.env.PGPORT ? Number(process.env.PGPORT) : 5432,
  database: process.env.PGDATABASE || "postgres_connection_issue",
  user: process.env.PGUSER,
});

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function main() {
  console.log("\n--- minimal idle timeout repro ---");
  try {
    await sql.begin(async (tx) => {
      await tx`SET idle_in_transaction_session_timeout = 50`;
      await sleep(200);
    });
  } catch (err) {
    // The driver throws a normal connection-closed error after the server kills
    // the backend for idling in a transaction. We log that and keep going.
    console.error("caught error:", err?.message || err);
  }
}

process.on("uncaughtException", (err) => {
  console.error("uncaught exception:", err);
});

main();

The stack trace is

    at Immediate.nextWrite ([..]/node_modules/postgres/cjs/src/connection.js:250:22)
    at process.processImmediate (node:internal/timers:483:21)

This seems to be a race condition between nextWrite and the socket being closed.

This becomes a problem because the exception cannot be caught without using process.on, ideally this exception would not be raised.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions