3B001 — invalid_savepoint_specification
3B001 — invalid_savepoint_specification
At a glance
3B001 means that a savepoint operation named a savepoint that is absent at the current transaction level. It is different from 25P01, which means there is no active transaction block at all.
| Field | Value |
|---|---|
| SQLSTATE | 3B001 |
| Condition | invalid_savepoint_specification |
| Status | active |
| Known present by | 8.0.0 |
| Locked snapshots | 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3 |
| Macros | ERRCODE_S_E_INVALID_SPECIFICATION |
| Aliases | — |
Meaning
The transaction manager raises 3B001 when ROLLBACK TO SAVEPOINT or a related savepoint operation cannot find the requested name in the current savepoint stack. PostgreSQL 18’s source template includes the name; the PG10 source uses the older no such savepoint wording. The missing name is a transaction-structure problem, not a table-data conflict.
Diagnosis
Capture SQLSTATE, primary message, transaction status, and the exact savepoint sequence. Check spelling, whether a savepoint was released, and whether a nested procedure or subtransaction changed the current savepoint level. After an ERROR inside an explicit block, the connection is INERROR; do not issue catalog or repair SQL there before rollback.
Response
Rollback the failed block, begin a new explicit transaction, and establish a savepoint whose name and nesting are known. If partial work should survive, use a correctly named savepoint before the risky statement and ROLLBACK TO that existing marker; a missing marker cannot be reconstructed after the error. Treat a retry as a new transaction plan and preserve the application’s normal idempotency checks.
Messages
18.6’s fixed source has savepoint "%s" does not exist and a related current-level variant. The selected PG10 output is no such savepoint. These are source-confirmed version/call differences; branch on 3B001 and transaction state rather than a single English message.
Representative case
verify/cases/3B001/snippets.json (SHA-256 595ce7692e34d36cc31df94c65c7040ee9bc4558fa887c23b56ba3187d235deb) contains an explicit BEGIN, an existing present savepoint, a ROLLBACK TO SAVEPOINT missing, and a rollback/repaired sequence. See the public case export and structured evidence.
The runner uses autocommit only to make each registry BEGIN/ROLLBACK/COMMIT boundary explicit. It asserts INERROR after the missing marker and IDLE after the recovery commit.
The selected case observed 3B001 on PostgreSQL 18.6 and 10.21. PostgreSQL 18 reported savepoint "missing" does not exist; PostgreSQL 10 reported no such savepoint. Both left the explicit block INERROR until ROLLBACK, after which a valid savepoint sequence committed.
Versions
The catalogue records 3B001 from its 8.0.0-or-earlier boundary through the formal snapshots. The selected 18.6 and 10.21 runs demonstrate the SQLSTATE and recovery boundary, while the primary message changed from the older generic wording to a named-savepoint template.
Related
See 3B000 savepoint exception for the class definition and 25P01 no active transaction when no transaction block exists.
Sources
src.errcodes.18.6(SHA-2566e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)src.xact.18.6(SHA-25675b012c0b047d1dc905a30975c244beec366e45eac0dbf109fd21bcd611a8e39)src.xact.10.23(SHA-2569120bd418bd0f18e3f1065a3772c92ff68f3be54e1a8c6d415043197f6daa47c)SAVEPOINT documentation· local call scansrc.calls.REL_18_6(SHA-2569ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)