2F002 — modifying_sql_data_not_permitted
SQLSTATE 2F002 names the standard SQL Routine Exception member for modifying SQL data when the routine’s declared data-access contract does not permit it. The locked PostgreSQL 18.6 definition contains the member, but its resolved core/contrib call scan has no native report group. Do not infer that PostgreSQL VOLATILE, STABLE, or IMMUTABLE alone maps to this SQLSTATE.
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
- SQL Routine Exception
- condition name
- modifying_sql_data_not_permitted
- lang
- en
- sqlstate
- 2F002
Definition PG 18
2F002
At a glance {#at-a-glance}
SQLSTATE 2F002 names the standard SQL Routine Exception member for modifying SQL data when the routine’s declared data-access contract does not permit it. The locked PostgreSQL 18.6 definition contains the member, but its resolved core/contrib call scan has no native report group. Do not infer that PostgreSQL VOLATILE, STABLE, or IMMUTABLE alone maps to this SQLSTATE.
Meaning {#meaning}
The condition is about a routine data-access restriction in an implementation that enforces that contract. The PostgreSQL catalogue row supplies identity and the macro; it does not establish a backend enforcement path or a particular routine language. An extension, embedded-SQL implementation, driver, or remote server may use the standard member independently.
Messages {#messages}
No fixed PostgreSQL message variant was adopted for this condition because the bounded scan did not resolve a native emitting call.
Diagnosis {#diagnosis}
First preserve the actual SQLSTATE and inspect the routine declaration and the owner that enforced it. Determine whether the attempted statement modified data, whether the routine was declared with a restrictive data-access characteristic, and whether the code came from a remote or client implementation. If the server returned another code, follow that code rather than treating 2F002 as a synonym for a PostgreSQL function volatility error.
Response {#response}
Change the routine’s data-access declaration only when the producing implementation documents that as the supported repair, or move the data-modifying work to an allowed routine boundary. Otherwise correct the caller or remote contract. Do not add a generic retry: a rejected data change did not by itself establish whether surrounding work was committed.
Versions {#versions}
The locked catalogue places this condition at least by PostgreSQL 7.4. The release definitions cover the published snapshots listed in the facts block; source-path status is limited to the fixed PostgreSQL 18.6 context cited below.
Related {#related}
Sources {#sources}
The fixed errcodes definition establishes the member and macro; the SQLSTATE appendix identifies the standard condition. The locked core/contrib scan found no resolved native 2F002 report group. See the structured evidence record for fixed source paths, scan scope, and unresolved runtime boundaries.
Compare versions
SQLSTATE evidence and recorded runtime versions
claims · identity
{
"claim_id": "identity",
"limits": "",
"method": "Read the fixed errcodes definition row, severity, and macro.",
"position": 0,
"runtime": [],
"sources": [
"src.errcodes.18.6"
],
"statement": "2F002 is modifying_sql_data_not_permitted in SQLSTATE Class 2F."
}claims · scan-boundary
{
"claim_id": "scan-boundary",
"limits": "The scan does not cover external wrappers, drivers, extensions, remote systems, or user code; absence from this scan is not an absolute absence claim.",
"method": "Compare resolved report groups with the fixed macro mapping.",
"position": 1,
"runtime": [],
"sources": [
"src.calls.REL_18_6",
"src.errcodes.18.6"
],
"statement": "No resolved 2F002 report group was found in the locked PostgreSQL 18.6 core/contrib call scan."
}claims · history-boundary
{
"claim_id": "history-boundary",
"limits": "Definition presence is not an emitting-path observation.",
"method": "Compare canonical release-definition facts with the available history boundary.",
"position": 2,
"runtime": [],
"sources": [
"src.errcodes.18.6"
],
"statement": "The locked release definitions establish catalogue presence from the known 7.4 boundary; they do not establish a precise introducing release or runtime use."
}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#L290"
}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": ""
}Source references
Full definition and evidence JSON
Definition sources
center · PostgreSQL 18 · english-manuals:e1209c57188d9dae08008e127f8a3015acb7fe7b832e107e3a8689eae6620a1b
Text language: en · english-manuals:e1209c57188d9dae08008e127f8a3015acb7fe7b832e107e3a8689eae6620a1b