Skip to content

Handle misuse rejects with TRANSACTION_ENDED or CONNECTION_RELEASED, not CONNECTION_ENDED - #185

Merged
okomarov merged 3 commits into
mainfrom
error-codes-138
Oct 23, 2026
Merged

okomarov merged 3 commits into
mainfrom
error-codes-138

Conversation

@okomarov

Copy link
Copy Markdown

A reserved handle used after release() now rejects with CONNECTION_RELEASED. A transaction handle used after its transaction ended, or while its COMMIT, ROLLBACK or PREPARE runs, now rejects with TRANSACTION_ENDED. Both come from Errors.generic, so the message names the mistake instead of reading write CONNECTION_ENDED host:port. CONNECTION_ENDED again means only that sql.end() was called, and CONNECTION_CLOSED is unchanged.

Five of the 20 most-starred apps using postgres retry CONNECTION_ENDED as transient, so use-after-release bugs were being retried and logged as connection blips.

  • The docs (api.md, lifecycle.md, upgrading.md) say which cases moved.
  • The switching tool's advice points at the new codes. Its CONNECTION_ENDED check drops to info, because code that checks for CONNECTION_ENDED behaves the same as on 3.4.9.

Closes #138

…s CONNECTION_CLOSED until the owner is done

Reserved handles after release() expect CONNECTION_RELEASED, transaction handles after their transaction ended expect TRANSACTION_ENDED, and CONNECTION_ENDED stays for sql.end(). A new scenario pins that a transaction handle leaked from a callback that outlived its dropped connection gets TRANSACTION_ENDED, not CONNECTION_CLOSED.
@okomarov
okomarov force-pushed the error-codes-138 branch 5 times, most recently from dbd7f6e to c20f997 Compare October 23, 2026 13:12
…SED, not CONNECTION_ENDED

A lease's state says what the handle is doing: Active (in use), Closed (in use, but its connection closed), Settling (a transaction finishing its COMMIT, ROLLBACK or PREPARE), Ended (a transaction that is over) or Released (a reservation that has been released). A transaction ends when its callback has finished, even if begin() already rejected because the connection closed. stop() records that and returns the connection only if the lease still holds it; the caller then releases or terminates it.

No longer CONNECTION_ENDED:
- a reserved handle used after release() or dispose: CONNECTION_RELEASED
- a statement queued on a reserved handle when release() ran: CONNECTION_RELEASED
- a transaction handle used after commit, rollback or prepare: TRANSACTION_ENDED
- a transaction handle used while COMMIT, ROLLBACK or PREPARE TRANSACTION is in flight: TRANSACTION_ENDED
- a savepoint on a transaction handle that started late or finished after the transaction ended: TRANSACTION_ENDED

No longer CONNECTION_CLOSED:
- a reserved handle used after release() when its connection had closed first: CONNECTION_RELEASED
- a transaction handle used after its begin() callback finished when its connection had closed first: TRANSACTION_ENDED

CONNECTION_ENDED now means only sql.end(): new queries, reserve() and begin() after it, and reserve() or begin() waiting when it was called.

Closes #138
…, and connection-ended-check is info

Handle misuse no longer raises CONNECTION_ENDED, so a retry set that lists it does not need the misuse codes. The README review examples drop the CONNECTION_ENDED mention.
@okomarov
okomarov merged commit 5264e6a into main Oct 23, 2026
30 of 31 checks passed
@okomarov
okomarov deleted the error-codes-138 branch October 23, 2026 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using a handle after release() or after its transaction ends rejects with CONNECTION_ENDED, the code for sql.end()

1 participant