↑↓ select↵ open⌫ change scopeOpen full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

Wiki / SQLSTATE

25P03 — idle_in_transaction_session_timeout

25P03 is a FATAL session-termination condition. It fires when a session is waiting for the next client query inside an open transaction longer than the effective idleintransactionsessiontimeout. The selected case uses 300 ms as a harness trigger, not as a production recommendation.

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
Invalid Transaction State
condition name
idle_in_transaction_session_timeout
lang
en
sqlstate
25P03

Definition PG 18

25P03 — idle_in_transaction_session_timeout

At a glance {#at-a-glance}

25P03 is a FATAL session-termination condition. It fires when a session is waiting for the next client query inside an open transaction longer than the effective idle_in_transaction_session_timeout. The selected case uses 300 ms as a harness trigger, not as a production recommendation.

Meaning {#meaning}

This timeout protects the server from sessions that keep an open transaction while waiting for the client; it can retain locks and delay cleanup. It applies while the session is idle in the transaction, including the idle in transaction and idle in transaction (aborted) states, not while an active statement is running. statement_timeout cancels a statement, while transaction_timeout covers the total transaction lifetime on versions that support it. The selected run covers the non-aborted INTRANS case only.

Diagnosis {#diagnosis}

Before the session disappears, capture its effective SHOW idle_in_transaction_session_timeout (or the matching pg_settings row) on that timed session itself. A control connection's SHOW or pg_settings describes the observer backend and cannot establish another session's effective SET value. From the control connection, inspect pg_stat_activity fields such as pid, usename, application_name, client_addr, state, xact_start, state_change, query_start, and query for state IN ('idle in transaction', 'idle in transaction (aborted)'). If the state is already aborted, preserve the earlier root error and 25P02 as separate diagnostics; the selected run is the non-aborted INTRANS path. These identify the pool or application path and how long it has been idle; permissions can limit what an observer sees. Correlate the FATAL record by backend PID, SQLSTATE, error_severity = FATAL, and exact message. The selected psycopg/libpq stack surfaced 25P03 in the driver diagnostic and CSV; PG18 also supplied JSON. The original connection is closed, so its transaction status cannot be repaired with ROLLBACK.

Response {#response}

Treat the session as gone: discard it from the pool and reconnect before retrying idempotent work. Prevent recurrence by committing or rolling back before returning a connection to the pool, and by fixing the application path that leaves a transaction open. Do not lower this timeout to suppress the error; a shorter value makes termination more likely. Choose an effective value above legitimate idle periods, or set it to 0 only when the deployment deliberately accepts the lock and cleanup risk. When the server closes this session, it rolls back the open incomplete transaction before exiting; the dead connection cannot accept a later ROLLBACK. A known uncommitted transaction on this terminated session cannot be recovered through that connection. If a separate network failure occurred after a COMMIT may have been sent, reconcile the business result from a fresh connection before retrying; that uncertainty is not implied by every 25P03 FATAL.

FATAL message {#messages}

The server source emits terminating connection due to idle-in-transaction timeout at FATAL severity; the original connection is terminated.

Observed diagnostics {#observed}

18.6 (Homebrew) / latest: FATAL SQLSTATE 25P03; primary terminating connection due to idle-in-transaction timeout; backend PID 26447; original connection closed True; collector CSV 25P03; collector JSON 25P03; fresh probe 1. 10.21 (Debian 10.21-1.pgdg90+1) / pg10: FATAL SQLSTATE 25P03; primary terminating connection due to idle-in-transaction timeout; backend PID 81; original connection closed True; collector CSV 25P03; collector JSON not applicable; fresh probe 1.

Representative case {#case}

The SQL excerpt below is not a paste-all script: run the setting, PID, and BEGIN on a test connection, then stop sending it queries while a separate observer or log collector waits for FATAL; after the old connection is terminated, open a fresh owner connection for the final probe. The runner reads these statements from the shared registry; complete assertions, collector correlation, environment, and cleanup are in case export.

-- set_timeout
SET idle_in_transaction_session_timeout = '300ms';
-- backend_pid
SELECT pg_backend_pid();
-- begin
BEGIN;
-- probe
SELECT 1;

The SQLSTATE, diagnostics, states, and repair assertions for this excerpt come from the shared registry (SHA-256 95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2); structured evidence.

Authored evidence IDs: identity, timeout-path, runtime. Selected runtime records: runtime.25P03-batch2c-latest-20260909.latest, runtime.25P03-batch2c-pg10-20260909.pg10.

Versions and limits {#versions}

The selected 300 ms termination case passes on PostgreSQL 18.6 and 10.21. PG18 has CSV and JSON collector records; PG10 has CSV only under its configured logging target. Both fresh owner connections run SELECT 1 successfully. The timeout value is deployment-specific; the case does not prescribe it.

Related {#related}

25P04 transaction timeout, 25006 read-only SQL transaction, 57014 query canceled.

Sources {#sources}

Compare versions

SQLSTATE evidence and recorded runtime versions

cases · idle_in_transaction_timeout
{
  "assertions": [
    "The original session is terminated by the timeout",
    "The collector records FATAL 25P03 for the matching backend PID",
    "A fresh connection can execute SELECT 1"
  ],
  "case_id": "idle_in_transaction_timeout",
  "cleanup": "Drop the case schema with an owner connection.",
  "has_snippet": true,
  "position": 0,
  "preconditions": [
    "A runner-owned disposable target is provisioned."
  ],
  "repair": "Use the state-specific recovery documented on the page; do not reuse a terminated connection.",
  "trigger": "Set idle_in_transaction_session_timeout, BEGIN, wait idle, and probe the terminated session.",
  "versions": [
    "10",
    "18"
  ]
}
claims · identity
{
  "claim_id": "identity",
  "limits": "The code is emitted at session termination severity FATAL in the selected path.",
  "method": "Read the fixed condition row and macro.",
  "position": 0,
  "runtime": [],
  "sources": [
    "src.errcodes.18.6"
  ],
  "statement": "25P03 is idle_in_transaction_session_timeout in Class 25."
}
claims · timeout-path
{
  "claim_id": "timeout-path",
  "limits": "The server terminates the connection; ROLLBACK cannot be sent through that dead session.",
  "method": "Trace the timeout interrupt and the fixed configuration documentation.",
  "position": 1,
  "runtime": [],
  "sources": [
    "src.postgres.18.6",
    "src.config.18.6",
    "src.calls.REL_18_6"
  ],
  "statement": "ProcessInterrupts emits FATAL 25P03 after the session has remained idle inside an open transaction longer than idle_in_transaction_session_timeout."
}
claims · runtime
{
  "claim_id": "runtime",
  "limits": "The selected timeout is 300 ms in a runner-owned disposable target; production timeout policy is deployment-specific.",
  "method": "Match collector records by PID, SQLSTATE, and message, then probe a fresh connection.",
  "position": 2,
  "runtime": [],
  "sources": [
    "runtime",
    "runtime.25P03-batch2c-latest-20260909.latest",
    "runtime.25P03-batch2c-pg10-20260909.pg10"
  ],
  "statement": "Both selected targets received FATAL 25P03 for the exact backend PID, and a fresh owner connection successfully ran SELECT 1 after termination."
}
claims · diagnosis-observer-boundary
{
  "claim_id": "diagnosis-observer-boundary",
  "limits": "Visibility of pg_stat_activity fields depends on observer privileges; the selected runtime records establish PID/log correlation, not universal monitoring permissions.",
  "method": "Read the fixed monitoring view documentation and system-view definition before writing the observer/session diagnostic split.",
  "position": 3,
  "runtime": [],
  "sources": [
    "doc.monitoring.18.6",
    "src.system_views.18.6"
  ],
  "statement": "The fixed monitoring documentation defines pg_stat_activity as one row per server process with current activity, including xact_start and state_change; pg_settings is defined over pg_show_all_settings for the current backend. Capture timeout settings on the timed session itself, because SHOW or pg_settings on an observer connection cannot establish another backend's effective SET value."
}
claims · state-scope
{
  "claim_id": "state-scope",
  "limits": "No aborted-transaction timeout was run in this batch; preserve any earlier root error and 25P02 separately when diagnosing that state.",
  "method": "Read the fixed pg_stat_activity state definitions alongside the timeout GUC description and compare them with the selected runtime status.",
  "position": 4,
  "runtime": [],
  "sources": [
    "doc.monitoring.18.6",
    "src.config.18.6"
  ],
  "statement": "The fixed monitoring view distinguishes idle in transaction from idle in transaction (aborted); the timeout documentation's open-transaction scope covers idle waiting, while the selected runtime demonstrates only the non-aborted INTRANS path."
}
claims · termination-rollback
{
  "claim_id": "termination-rollback",
  "limits": "This establishes server-side rollback on forced connection close; it does not resolve a separate network failure after a client may have sent COMMIT.",
  "method": "Read the fixed protocol session-termination rule and align the recovery prose with the FATAL path.",
  "position": 5,
  "runtime": [],
  "sources": [
    "doc.protocol.18.6"
  ],
  "statement": "The fixed protocol documentation states that when the backend closes a connection it rolls back any open incomplete transaction before exiting; the driver cannot send a later ROLLBACK on that closed session."
}
messages · fatal
{
  "limits": "This is a static FATAL message; the driver may expose or omit SQLSTATE depending on client stack.",
  "message_id": "fatal",
  "path": "",
  "position": 0,
  "raw": {
    "id": "fatal",
    "limits": "This is a static FATAL message; the driver may expose or omit SQLSTATE depending on client stack.",
    "primary_template": "terminating connection due to idle-in-transaction timeout",
    "severity_source": "FATAL",
    "sources": [
      "src.postgres.18.6"
    ],
    "sqlstate": "25P03"
  },
  "severity": "FATAL",
  "sources": [
    "src.postgres.18.6"
  ],
  "templates": [
    {
      "kind": "primary",
      "literal": "terminating connection due to idle-in-transaction timeout",
      "position": 0,
      "role": "",
      "template": "terminating connection due to idle-in-transaction timeout"
    }
  ]
}
runtimes · runtime.25P03-batch2c-latest-20260909.latest · 18.6 (Homebrew) · passed
{
  "cases": [
    "idle_in_transaction_timeout"
  ],
  "limits": "",
  "position": 0,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25P03/cases.json",
      "sha256": "e6c8d08f3b964c308d1a2c87f64919aa7d914db438456658afa230383c7f27eb"
    },
    "case_status": "passed",
    "cases": [
      "idle_in_transaction_timeout"
    ],
    "id": "runtime.25P03-batch2c-latest-20260909.latest",
    "observed": {
      "backend_pid": 26447,
      "collector_csv_error_severity": "FATAL",
      "collector_csv_sqlstate": "25P03",
      "collector_json_error_severity": "FATAL",
      "collector_json_sqlstate": "25P03",
      "fresh_connection_probe": 1,
      "fresh_connection_status": "IDLE",
      "original_connection_closed": true,
      "primary": "terminating connection due to idle-in-transaction timeout",
      "recovery_requires_new_connection": true,
      "severity": "FATAL",
      "sqlstate": "25P03",
      "status_before_timeout": "INTRANS"
    },
    "raw": "verify/results/25P03-batch2c-latest-20260909/latest/raw.jsonl",
    "raw_sha256": "eeb467a1908730a03d6eb9cf1e1319a5d658dcb4a0bb42d0907f8045682778bf",
    "run_id": "25P03-batch2c-latest-20260909",
    "server_version": "18.6 (Homebrew)",
    "server_version_num": 180006,
    "snippet_registry": {
      "path": "verify/cases/25P03/snippets.json",
      "sha256": "95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2"
    },
    "status": "passed",
    "summary": "verify/results/25P03-batch2c-latest-20260909/latest/summary.json",
    "summary_sha256": "ec210989486eb92bda87e874942b5987d23f121f914c780e30851f3fe04e9379",
    "target": "latest",
    "target_status": "passed"
  },
  "run_id": "25P03-batch2c-latest-20260909",
  "runtime_id": "runtime.25P03-batch2c-latest-20260909.latest",
  "server_version": "18.6 (Homebrew)",
  "status": "passed",
  "target": "latest"
}
runtimes · runtime.25P03-batch2c-pg10-20260909.pg10 · 10.21 (Debian 10.21-1.pgdg90+1) · passed
{
  "cases": [
    "idle_in_transaction_timeout"
  ],
  "limits": "",
  "position": 1,
  "raw": {
    "case_manifest": {
      "path": "verify/cases/25P03/cases.json",
      "sha256": "e6c8d08f3b964c308d1a2c87f64919aa7d914db438456658afa230383c7f27eb"
    },
    "case_status": "passed",
    "cases": [
      "idle_in_transaction_timeout"
    ],
    "id": "runtime.25P03-batch2c-pg10-20260909.pg10",
    "observed": {
      "backend_pid": 81,
      "collector_csv_error_severity": "FATAL",
      "collector_csv_sqlstate": "25P03",
      "collector_json_error_severity": null,
      "collector_json_sqlstate": null,
      "fresh_connection_probe": 1,
      "fresh_connection_status": "IDLE",
      "original_connection_closed": true,
      "primary": "terminating connection due to idle-in-transaction timeout",
      "recovery_requires_new_connection": true,
      "severity": "FATAL",
      "sqlstate": "25P03",
      "status_before_timeout": "INTRANS"
    },
    "raw": "verify/results/25P03-batch2c-pg10-20260909/pg10/raw.jsonl",
    "raw_sha256": "cc716ef184879dac6e0e6885922e940faa0bfed5ef22ef64e479403db499c7e8",
    "run_id": "25P03-batch2c-pg10-20260909",
    "server_version": "10.21 (Debian 10.21-1.pgdg90+1)",
    "server_version_num": 100021,
    "snippet_registry": {
      "path": "verify/cases/25P03/snippets.json",
      "sha256": "95fd079c8bca77c6e3ffc398e404a218e4f810e5fa36e30127cbc6470a6d6eb2"
    },
    "status": "passed",
    "summary": "verify/results/25P03-batch2c-pg10-20260909/pg10/summary.json",
    "summary_sha256": "a76cbc2408369f7baca614ed533cba18d8b7f105d7fd3319107be5c01143917d",
    "target": "pg10",
    "target_status": "passed"
  },
  "run_id": "25P03-batch2c-pg10-20260909",
  "runtime_id": "runtime.25P03-batch2c-pg10-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.postgres.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/tcop/postgres.c",
  "position": 2,
  "sha256": "9fb62275b1badf94d01ab351337b60410cd9b3ab1fe63fa9f23d6d2185a21061",
  "source_id": "src.postgres.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L3473-L3501"
}
sources · src.config.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/runtime-config-client.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/config.sgml",
  "position": 3,
  "sha256": "ffca322c15315ba670733d6b320f23cbba7374db0d18937298ffc07b58799ef6",
  "source_id": "src.config.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/config.sgml#L10252-L10347"
}
sources · doc.monitoring.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/monitoring-stats.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/monitoring.sgml",
  "position": 4,
  "sha256": "06b147f8d966fe46821871703ffcee8a3449cc3f7de5b64b9177f48569fe96f6",
  "source_id": "doc.monitoring.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/monitoring.sgml#L706-L875"
}
sources · src.system_views.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/view-pg-settings.html",
  "kind": "upstream_source",
  "location": "",
  "path": "src/backend/catalog/system_views.sql",
  "position": 5,
  "sha256": "418f4ae7472fe0742e6fbdc7a055581602c5131e082aa6f17e2c7269bf711972",
  "source_id": "src.system_views.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/catalog/system_views.sql#L604-L605"
}
sources · doc.protocol.18.6
{
  "commit": "724edf9bde9d356724ad384a2e196edc3c9f80f7",
  "docs_url": "https://www.postgresql.org/docs/18/protocol.html",
  "kind": "upstream_source",
  "location": "",
  "path": "doc/src/sgml/protocol.sgml",
  "position": 6,
  "sha256": "745339e07ebbc2bb67d98b258e25772ada644ef26011e3cd6b3fcbb435235f89",
  "source_id": "doc.protocol.18.6",
  "tag": "REL_18_6",
  "url": "https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/protocol.sgml#L61-L65"
}

Source references

Full definition and evidence JSON

Definition sources

center · PostgreSQL 18 · english-manuals:1db52d3da9a813f5a4ad9099aae2dc662e759b68aa365475726e0f99ee98adc1

Text language: en · english-manuals:1db52d3da9a813f5a4ad9099aae2dc662e759b68aa365475726e0f99ee98adc1