53300
Read PG 18 manual ↗too_many_connections
- SQLSTATE
- 53300
- Condition name
- too_many_connections
- Class
- Insufficient Resources
- Source macro
- ERRCODE_TOO_MANY_CONNECTIONS
- Evidence
- Observed at runtime in the source evidence
English SQLSTATE atlas: authored explanations and source/runtime evidence are separate from the manual definitions. View source ↗
At a glance
53300 is PostgreSQL's too_many_connections condition in Class 53, insufficient_resources. It is emitted when a new backend cannot be admitted because a connection capacity limit has been reached. The representative case uses a role connection limit of one and opens a second session for that role.
This is a connection-startup failure. No SQL transaction is opened for the rejected session. In the final runs, psycopg reported the startup exception text but exposed sqlstate=None; the PostgreSQL collector recorded the server's actual FATAL SQLSTATE 53300. Keep those observations separate when diagnosing a connection pool or an authentication gateway.
The case role_connection_limit passed on PostgreSQL 18.6 and the isolated PostgreSQL 10.21 target. The run IDs and per-case assertions are retained in the public evidence JSON.
Meaning and trigger paths
During backend startup, PostgreSQL checks the authenticated role's rolconnlimit after creating the backend bookkeeping entry. For a non-superuser role with a nonnegative limit, a count above that limit raises FATAL with ERRCODE_TOO_MANY_CONNECTIONS and the message too many connections for role "%s". The source comments describe this role count as approximate because simultaneous startups can race.
The same SQLSTATE can identify another capacity path, such as a server-wide client limit. The role-limit case here does not establish the cause of every 53300; use the primary message, collector fields, and the configured role, database, and server limits to classify it.
Because the failure occurs before the SQL protocol reaches a transaction, transaction status is not INERROR or IDLE for the rejected session. A management or pool connection that remains open can change the limit and then prove recovery with a new session.
Messages and diagnostics
The executable excerpt uses the same role-limit SQL statements as the runner. limited_user is replaced by a disposable role in the isolated run. The second connection is a separate client-startup operation, so it is described between the SQL statements rather than represented by a fabricated SQL command.
ALTER ROLE limited_user CONNECTION LIMIT 1;
-- Keep one session open as limited_user.
-- Open a second session as limited_user: startup returns FATAL 53300.
ALTER ROLE limited_user CONNECTION LIMIT -1;
SELECT 1;
The latest target's collector record was:
SQLSTATE: 53300 # csvlog/jsonlog sql_state_code
severity: FATAL
message_primary: too many connections for role "<generated-role>"
source: miscinit.c / InitializeSessionUserId / line 880
driver startup sqlstate: null
transaction: none opened
repair: reset CONNECTION LIMIT; fresh role connection SELECT 1 -> 1
PostgreSQL 10.21 produced the same message and SQLSTATE in its collector, with the source location miscinit.c:575. In both targets the known role connection succeeded after the limit was reset. The role name and port above are run-generated values; the collector's sql_state_code is the server evidence. A startup error may not expose a SQLSTATE property through a particular driver.
Diagnosis
Capture the connection parameters without secrets, the role and database, the server version, the exact startup text, and a collector record correlated by time, user, and connection source. Check pg_roles.rolconnlimit, database and server connection settings, and current backend counts. A pool can exhaust a role limit while the server still has global capacity.
Treat the role count as a capacity observation rather than an exact admission proof under a burst: PostgreSQL documents an approximate check for concurrent startups. Check the primary message before changing a global setting, and preserve an administrative path for recovery.
Do not issue transaction cleanup commands for the rejected session. It never reached a usable SQL transaction. A still-open owner or administration connection can restore the setting; the meaningful repair assertion is a fresh login for the affected role followed by a real query.
Response and repair
- Bound pool size and connection concurrency so a role does not repeatedly exhaust its limit.
- Increase the role, database, or server capacity only after checking memory, workload, and the intended admission policy.
- Keep reserved capacity and a controlled administrative connection for recovery; do not grant superuser status merely to bypass a limit.
- After changing the limit, open a new connection and execute a harmless query. Reconcile pool state and close stale sessions before retrying application work.
The representative repair reset the disposable role's limit, opened a new role connection, and observed SELECT 1 as 1. That proves recovery of this role-limit path; it does not prove that a different database-wide or server-wide capacity failure has been repaired.
Versions and boundaries
The catalogue has a definition-presence observation for 53300 at PostgreSQL 7.4 and through the locked 8.4.22 pre-9.0 definitions, then in every listed formal snapshot through PostgreSQL 18.6 and the PostgreSQL 19 Beta 3 preview. This is a definition-only presence boundary, not an exact implementation introduction or runtime-use claim. The class title change between the 9.0 header and 9.1 text definitions is recorded in the catalogue; it is not an asserted implementation change for this condition.
The role-limit case passed on PostgreSQL 18.6 and 10.21. Source line numbers differ, and the driver/collector split is part of the observed boundary. Database-wide and server-wide capacity paths, connection pool behavior, and operating-system resource exhaustion require their own evidence.
Sources
Structured evidence is recorded in the public evidence JSON. Source records are fixed to PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7; runtime records retain the collector output, driver observation, both target IDs, and structured observations.
src.errcodes.18.6—errcodes.txtsrc.miscinit.18.6—miscinit.csrc.backend-startup.18.6—backend_startup.cdoc.protocol.18— Error and Notice Message Fields- Runtime:
53300-registry-final-20260909on latest and pg10; structured observations are in the public evidence JSON
Source evidence
Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.
53300 is the too_many_connections condition in Class 53 insufficient_resources.
Method: Read the Class 53 section and 53300 row in the frozen errcodes.txt snapshot.
Limits: Directory identity does not identify whether a role, database, or server-wide capacity limit caused an occurrence.
During backend startup, a non-superuser role whose CountUserBackends result exceeds rolconnlimit receives FATAL SQLSTATE 53300 with too many connections for role "%s"; the source documents the count check as approximate under a race.
Method: Read the role connection-limit branch, explicit ERRCODE_TOO_MANY_CONNECTIONS, message construction, and concurrency comment.
Limits: This source path is role-specific; other capacity paths can use 53300 with different messages.
The server-wide startup capacity gate also reports SQLSTATE 53300 at FATAL with sorry, too many clients already.
Method: Read the CAC_TOOMANY backend-startup branch in the fixed source.
Limits: This is a source-confirmed server-wide startup gate; it is not covered by the role-limit runtime case and does not classify database or operating-system resource failures.
For the rejected startup connection, psycopg exposed startup text with sqlstate null while the PostgreSQL collector recorded FATAL SQLSTATE 53300 and the role-limit message on both targets.
Method: Compare the driver diagnostic, CSV collector state_code, message, severity, and source location in both final summaries and raw records.
Limits: Driver exposure can vary by client and startup failure; the collector record is the server-side SQLSTATE evidence here.
doc.protocol.18 runtime.53300-registry-final-20260909.latest runtime.53300-registry-final-20260909.pg10
After resetting the disposable role's connection limit, a fresh connection for that role executed SELECT 1 and returned 1 on PostgreSQL 18.6 and 10.21.
Method: Keep one holder session, trigger the second startup, restore the limit through an owner connection, and assert a new role session and query.
Limits: The repair proves the role-limit path only; it does not prove recovery of another global capacity limit.
case-manifest.53300 snippet-registry.53300.final runtime.53300-registry-final-20260909.latest runtime.53300-registry-final-20260909.pg10
The locked catalogue records 53300 in every listed formal snapshot from 9.0.23 through 18.6 and in 19beta3; pre-9.0 history is not scanned.
Method: Read the manifest snapshots and definition references for the code.
Limits: The first scanned release is a lower bound, not an asserted introduction version.
- src/backend/utils/errcodes.txt · REL_18_6 · lines 407-414
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/tcop/backend_startup.c · REL_18_6 · lines 340-344
724edf9bde9d356724ad384a2e196edc3c9f80f7 - src/backend/utils/init/miscinit.c · REL_18_6 · lines 868-880
724edf9bde9d356724ad384a2e196edc3c9f80f7 - doc/src/sgml/protocol.sgml · PG18-docs · ErrorResponse fields
724edf9bde9d356724ad384a2e196edc3c9f80f7 - sources/manifest.lock.json · · snapshots and definition_blobs entries for the 53300 definition
- verify/cases/53300/cases.json · · role_connection_limit
- verify/cases/53300/snippets.json · · role_connection_limit ordered SQL
Message templates
explicit FATAL · message.server-capacity
Primary
sorry, too many clients already
This template belongs to the server-wide startup gate and is distinct from the role-limit template.
explicit FATAL · message.role-limit
Primary
too many connections for role "%s"
The role name is dynamically inserted; database-wide and server-wide capacity branches may use another primary template.
Reproduction & repair cases
role_connection_limit · PG 10, 18
Preconditions
- A disposable login role
- The role connection limit is set to one while one session is already connected
Trigger: Open a second connection for that role.
Expected assertions
- The new connection receives FATAL SQLSTATE 53300
- The existing owner connection can restore the limit and continue
Repair: Pool and bound connections, reserve capacity for administration, and investigate the role/database/server limit that was reached.
Cleanup: Restore the role limit, drop the role, and drop the case schema.
Recorded runtime evidence
18.6 (Homebrew) · passed
Run: 53300-registry-final-20260909
{
"driver_text": "FATAL: too many connections for role <generated-role>",
"transaction": "none opened for rejected startup",
"restored_query": 1,
"driver_sqlstate": null,
"collector_source": "miscinit.c:880",
"collector_message": "too many connections for role <generated-role>",
"collector_severity": "FATAL",
"collector_sqlstate": "53300"
}10.21 (Debian 10.21-1.pgdg90+1) · passed
Run: 53300-registry-final-20260909
{
"driver_text": "FATAL: too many connections for role <generated-role>",
"transaction": "none opened for rejected startup",
"restored_query": 1,
"driver_sqlstate": null,
"collector_source": "miscinit.c:575",
"collector_message": "too many connections for role <generated-role>",
"collector_severity": "FATAL",
"collector_sqlstate": "53300"
}Definition snapshot: english-manuals:e78546c5424b0240399959e3747… · English manual source