v4: a connection error without a stack (Bun DNSException) throws in withOrigin, so the query hangs forever and the pool never retries

Open Beginner friendly
#1,312 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 2 days

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
bun, javascript, postgresql

Research direction

Start with src/errors.js:65 and trace how src/pool.js handles a failed connection through failed, attempted, and reject. Reproduce the issue on Bun with a hostname that does not resolve, then verify the query rejects instead of hanging; also check that errors with a stack still retain their existing message behavior.

Written by the indexing model from the issue text.

Description

Summary

withOrigin (src/errors.js:65) assumes every connection error has a stack string. When it doesn't, it throws inside the pool's failure handling (failed → attempted → reject in src/pool.js). The pending query never settles, grow() is never reached so no retry happens, and the process hangs forever.

Bun's DNS errors have no stack (DNSException, e.g. EAI_AGAIN), so on Bun any query against a host that doesn't resolve hangs instead of rejecting.

Reproduction (postgres 4.1.0, Bun 1.4.4)

import postgres from 'postgres'
const sql = postgres('postgres://user:[email protected]:5432/db', { max: 1 })
await sql`select 1` // never settles

Output:

TypeError: undefined is not an object (evaluating 'error.stack.split')
      at withOrigin (node_modules/postgres/src/errors.js:65:19)
      at reject (node_modules/postgres/src/pool.js:575:58)
      at forEach (1:11)
      at attempted (node_modules/postgres/src/pool.js:570:71)
      at failed (node_modules/postgres/src/pool.js:557:5)

With ECONNREFUSED (an error that has a stack) the query rejects as expected.

Fix

Changing only that line makes the query reject in ~4 ms with EAI_AGAIN:

-    value: [error.stack.split('\n')[0], ...origin.split('\n').slice(1).filter(x => !ours(x))].join('\n'),
+    value: [String(error.stack ?? error.message).split('\n')[0], ...origin.split('\n').slice(1).filter(x => !ours(x))].join('\n'),

More generally, an exception thrown while rejecting jobs should not leave them pending.

Impact

We hit this in production: after a Docker Swarm host reboot, the database service name did not resolve for a few seconds when the app started. The startup query hung instead of failing, so the container never exited and Swarm never restarted it; the app was down for ~6 hours.

Dominant language
JavaScript
Stars
8.8k
Forks
404
Avg merge
21h 8m
Merged PRs (30d)
18

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

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.

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.