porsager / porsager/postgres

Uncatchable exception on idle in transcation timeout

Open
#1,133 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
8.7k
Forks
374
Avg merge
11d 16h
Merged PRs (30d)
1

Description

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the minimal reproduction in the issue and inspect connection.js around nextWrite at line 250, focusing on the interaction with the socket closing after the idle-in-transaction timeout. Confirm the uncaught exception and verify that the same scenario completes with the connection-closed error handled at the callsite rather than reaching process.on("uncaughtException").

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs, postgresql
Domain
backend, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.