psycopg/psycopg2 · error · PoolError
connection pool is closed
Error message
connection pool is closed
What it means
Raised by AbstractConnectionPool._getconn() (lib/pool.py:78-79) when getconn() is called on a pool whose 'closed' flag is True. closeall() sets closed=True (lib/pool.py:144); after that the pool refuses to hand out connections because all underlying connections have been closed and the pool is decommissioned.
Source
Thrown at lib/pool.py:79
def _connect(self, key=None):
"""Create a new connection and assign it to 'key' if not None."""
conn = psycopg2.connect(*self._args, **self._kwargs)
if key is not None:
self._used[key] = conn
self._rused[id(conn)] = key
else:
self._pool.append(conn)
return conn
def _getkey(self):
"""Return a new unique key."""
self._keys += 1
return self._keys
def _getconn(self, key=None):
"""Get a free connection and assign it to 'key' if not None."""
if self.closed:
raise PoolError("connection pool is closed")
if key is None:
key = self._getkey()
if key in self._used:
return self._used[key]
if self._pool:
self._used[key] = conn = self._pool.pop()
self._rused[id(conn)] = key
return conn
else:
if len(self._used) == self.maxconn:
raise PoolError("connection pool exhausted")
return self._connect(key)
def _putconn(self, conn, key=None, close=False):
"""Put away a connection."""
if self.closed:View on GitHub (pinned to 3a6d9d6ddc)
Solutions
- Order shutdown so that closeall() is called only after all workers have released their connections.
- Guard getconn() callers with a check of pool.closed, or wrap acquisition in try/except psycopg2.pool.PoolError.
- In multi-threaded code, use a coordination point (e.g. an event) so threads stop requesting before closeall().
- Create a fresh pool for a new lifecycle instead of reusing a closed one.
Example fix
// before pool.closeall() conn = pool.getconn() # shutdown race // after # drain workers first, then: for t in workers: t.join() pool.closeall()
Defensive patterns
Strategy: validation
Validate before calling
if pool.closed:
raise RuntimeError('cannot getconn from a closed pool; create a new pool')
conn = pool.getconn() Type guard
def pool_is_usable(pool) -> bool:
return not getattr(pool, 'closed', False) Try / catch
try:
conn = pool.getconn()
except psycopg2.pool.PoolError as e:
if 'closed' in str(e):
pool = create_new_pool(...)
conn = pool.getconn()
else: raise Prevention
- Coordinate shutdown: drain workers before closeall().
- Check pool.closed before acquiring in long-lived loops.
When it happens
Trigger: Calling pool.getconn() (or _getconn) after pool.closeall() has been invoked. In threaded pools (ThreadedConnectionPool) this can happen when one thread closes the pool while another tries to acquire a connection.
Common situations: Application shutdown sequences where closeall() runs before all worker threads have finished, or request handlers that lazily grab a connection after a background health-check closed the pool. Also seen in test teardown that closes the pool before fixtures release their connections.
Related errors
AI-assisted analysis of psycopg/psycopg2@3a6d9d6ddc (2026-08-04).
Data as JSON: /data/errors/e681cd975acde8c4.json.
Report an issue: GitHub.