3B001 — invalid_savepoint_specification
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.
English manual coverage begins with PostgreSQL 8.1. Source history and runtime observations have their own recorded version boundaries.
Reading PG 18·Select a recorded version
- aliases
- Unknown
- class name
- Savepoint Exception
- condition name
- invalid_savepoint_specification
- lang
- en
- sqlstate
- 3B001
Definition PG 18
3B001 — invalid_savepoint_specification
At a glance {#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.
Meaning {#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 {#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 {#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 {#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 {#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.
BEGIN;
SAVEPOINT present;
ROLLBACK TO SAVEPOINT missing;
ROLLBACK;
BEGIN;
SAVEPOINT present;
RELEASE SAVEPOINT present;
COMMIT;
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 {#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 {#related}
See 3B000 savepoint exception for the class definition and 25P01 no active transaction when no transaction block exists.
Sources {#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)
Compare versions
SQLSTATE evidence and recorded runtime versions
cases · invalid_savepoint_recovery
{
"assertions": [
"SQLSTATE is 3B001",
"The diagnostic identifies the missing savepoint",
"The failed block is INERROR until ROLLBACK",
"A valid SAVEPOINT/RELEASE/COMMIT succeeds afterward"
],
"case_id": "invalid_savepoint_recovery",
"cleanup": "Drop the case schema with an owner connection.",
"has_snippet": true,
"position": 0,
"preconditions": [
"A runner-owned disposable target is provisioned."
],
"repair": "Verify the savepoint name and nesting level; rollback the failed block before issuing a new savepoint sequence.",
"trigger": "Inside a valid explicit transaction, roll back to a savepoint name that was never established, then rollback and establish a valid savepoint.",
"versions": [
"10",
"18"
]
}claims · identity
{
"claim_id": "identity",
"limits": "The class-level 3B000 entry is separate from this specific condition.",
"method": "Read the fixed errcodes.txt row and macro mapping.",
"position": 0,
"runtime": [],
"sources": [
"src.errcodes.18.6"
],
"statement": "3B001 is the invalid_savepoint_specification condition in Class 3B."
}claims · savepoint-path
{
"claim_id": "savepoint-path",
"limits": "PG10 uses the older no such savepoint wording; the SQLSTATE and state transition are the stable facts here.",
"method": "Trace ERRCODE_S_E_INVALID_SPECIFICATION in xact.c.",
"position": 1,
"runtime": [],
"sources": [
"src.xact.18.6",
"src.calls.REL_18_6"
],
"statement": "RollbackToSavepoint emits a missing-savepoint error when the named savepoint is not present at the current level."
}claims · recovery
{
"claim_id": "recovery",
"limits": "A valid savepoint at another nesting level is a different case.",
"method": "Run the shared explicit BEGIN/SAVEPOINT/ROLLBACK case and inspect transaction status.",
"position": 2,
"runtime": [],
"sources": [
"doc.savepoint.18.6"
],
"statement": "A failed ROLLBACK TO SAVEPOINT leaves the explicit transaction in error; ROLLBACK ends that block before a new savepoint sequence."
}claims · runtime
{
"claim_id": "runtime",
"limits": "This covers the selected mechanism only, not all source callers or all driver/pool behavior.",
"method": "Read the selected runner summaries and raw outputs tied to the shared snippet registry.",
"position": 3,
"runtime": [],
"sources": [
"runtime.3B001-batch34-20260909.latest",
"runtime.3B001-batch34-20260909.pg10"
],
"statement": "The selected 3B001 case passed on PostgreSQL 18.6 and 10.21 with the structured SQLSTATE, transaction-state, and repair assertions recorded in the runtime entries."
}messages · message.savepoint-modern
{
"limits": "The name is dynamic.",
"message_id": "message.savepoint-modern",
"path": "",
"position": 0,
"raw": {
"id": "message.savepoint-modern",
"limits": "The name is dynamic.",
"primary_template": "savepoint \"%s\" does not exist",
"severity_source": "ERROR",
"sources": [
"src.xact.18.6"
],
"sqlstate": "3B001"
},
"severity": "ERROR",
"sources": [
"src.xact.18.6"
],
"templates": [
{
"kind": "primary",
"literal": "savepoint \" \" does not exist",
"position": 0,
"role": "",
"template": "savepoint \"%s\" does not exist"
}
]
}messages · message.savepoint-pg10
{
"limits": "PG10 wording omits the savepoint name.",
"message_id": "message.savepoint-pg10",
"path": "",
"position": 1,
"raw": {
"id": "message.savepoint-pg10",
"limits": "PG10 wording omits the savepoint name.",
"primary_template": "no such savepoint",
"severity_source": "ERROR",
"sources": [
"src.xact.10.23"
],
"sqlstate": "3B001"
},
"severity": "ERROR",
"sources": [
"src.xact.10.23"
],
"templates": [
{
"kind": "primary",
"literal": "no such savepoint",
"position": 0,
"role": "",
"template": "no such savepoint"
}
]
}runtimes · runtime.3B001-batch34-20260909.latest · 18.6 (Homebrew) · passed
{
"cases": [
"invalid_savepoint_recovery"
],
"limits": "",
"position": 0,
"raw": {
"case_manifest": {
"path": "verify/cases/3B001/cases.json",
"sha256": "084e2bb92c6ed5388c30ece2406512434e8134c17880a2c8b8cdecdaca5001bc"
},
"cases": [
"invalid_savepoint_recovery"
],
"id": "runtime.3B001-batch34-20260909.latest",
"observed": {
"connection_autocommit": true,
"primary": "savepoint \"missing\" does not exist",
"repair": {},
"severity": "ERROR",
"sqlstate": "3B001",
"statuses": {
"after_error": "INERROR",
"after_repair": "IDLE",
"after_rollback": "IDLE"
}
},
"raw": "verify/results/3B001-batch34-20260909/latest/raw.jsonl",
"raw_sha256": "f01798df2d267371cc2eca0422cf862edf0c30a58edefa138b5a8c2bd451dab5",
"run_id": "3B001-batch34-20260909",
"server_version": "18.6 (Homebrew)",
"snippet_registry": {
"path": "verify/cases/3B001/snippets.json",
"sha256": "595ce7692e34d36cc31df94c65c7040ee9bc4558fa887c23b56ba3187d235deb"
},
"status": "passed",
"summary": "verify/results/3B001-batch34-20260909/latest/summary.json",
"summary_sha256": "8299597b2f31d38a52997a7386c65d71a3dd433a8bf69583bc1f55f6c5e67b95",
"target": "latest"
},
"run_id": "3B001-batch34-20260909",
"runtime_id": "runtime.3B001-batch34-20260909.latest",
"server_version": "18.6 (Homebrew)",
"status": "passed",
"target": "latest"
}runtimes · runtime.3B001-batch34-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
"cases": [
"invalid_savepoint_recovery"
],
"limits": "",
"position": 1,
"raw": {
"case_manifest": {
"path": "verify/cases/3B001/cases.json",
"sha256": "084e2bb92c6ed5388c30ece2406512434e8134c17880a2c8b8cdecdaca5001bc"
},
"cases": [
"invalid_savepoint_recovery"
],
"id": "runtime.3B001-batch34-20260909.pg10",
"observed": {
"connection_autocommit": true,
"primary": "no such savepoint",
"repair": {},
"severity": "ERROR",
"sqlstate": "3B001",
"statuses": {
"after_error": "INERROR",
"after_repair": "IDLE",
"after_rollback": "IDLE"
}
},
"raw": "verify/results/3B001-batch34-20260909/pg10/raw.jsonl",
"raw_sha256": "66ae381dc1edbb309a234751738e015d5bd34b38777f7ae66e7b6eeee549ce91",
"run_id": "3B001-batch34-20260909",
"server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
"snippet_registry": {
"path": "verify/cases/3B001/snippets.json",
"sha256": "595ce7692e34d36cc31df94c65c7040ee9bc4558fa887c23b56ba3187d235deb"
},
"status": "passed",
"summary": "verify/results/3B001-batch34-20260909/pg10/summary.json",
"summary_sha256": "7e4de60ee83cc2e565050d93648c16006a266d3f584f8d1b096aef89b546ebe2",
"target": "pg10"
},
"run_id": "3B001-batch34-20260909",
"runtime_id": "runtime.3B001-batch34-20260909.pg10",
"server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
"status": "passed",
"target": "pg10"
}sources · src.errcodes.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/utils/errcodes.txt",
"position": 0,
"sha256": "6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba",
"source_id": "src.errcodes.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt"
}sources · src.calls.REL_18_6
{
"commit": "",
"docs_url": "",
"kind": "local_artifact",
"location": "",
"path": "raw/calls/REL_18_6.jsonl",
"position": 1,
"sha256": "9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf",
"source_id": "src.calls.REL_18_6",
"tag": "",
"url": ""
}sources · src.xact.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/access/transam/xact.c",
"position": 2,
"sha256": "75b012c0b047d1dc905a30975c244beec366e45eac0dbf109fd21bcd611a8e39",
"source_id": "src.xact.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/access/transam/xact.c#L4482-L4484"
}sources · src.xact.10.23
{
"commit": "02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4",
"docs_url": "",
"kind": "upstream_source",
"location": "",
"path": "src/backend/access/transam/xact.c",
"position": 3,
"sha256": "9120bd418bd0f18e3f1065a3772c92ff68f3be54e1a8c6d415043197f6daa47c",
"source_id": "src.xact.10.23",
"tag": "REL_10_23",
"url": "https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/access/transam/xact.c#L3914-L3916"
}sources · doc.savepoint.18.6
{
"commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
"docs_url": "https://www.postgresql.org/docs/18/sql-savepoint.html",
"kind": "upstream_source",
"location": "",
"path": "doc/src/sgml/ref/savepoint.sgml",
"position": 4,
"sha256": "aa6e167d373da6118249c87404a7b2ff8be8c7df790449814f1d9dc433bbd428",
"source_id": "doc.savepoint.18.6",
"tag": "REL_18_6",
"url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ref/savepoint.sgml"
}Source references
Full definition and evidence JSON
Definition sources
center · PostgreSQL 18 · english-manuals:3a16430ec0f037fb2cfa2359bc98bbd7c401b2ee0c9e32e01526e817cb825130
Text language: en · english-manuals:3a16430ec0f037fb2cfa2359bc98bbd7c401b2ee0c9e32e01526e817cb825130