Report #71759
[bug\_fix] prepared statement "X" does not exist \(SQLSTATE 26000 / invalid\_sql\_statement\_name\)
Disable prepared statements in the database driver configuration \(e.g., for PostgreSQL JDBC set prepareThreshold=0; for psycopg2 set prepare\_threshold=None or use a connection factory with prepare\_threshold=0; for asyncpg do not use prepared statements\), or switch PgBouncer from transaction pooling mode to session pooling mode.
Journey Context:
An application operates perfectly when connecting directly to PostgreSQL, but after introducing PgBouncer in transaction pooling mode to handle higher concurrency and reduce connection overhead, queries begin failing with prepared statement "pg8000\_0" does not exist or similar errors with SQLSTATE 26000. Debugging reveals that modern PostgreSQL drivers \(psycopg2, pg8000, JDBC, asyncpg\) automatically use server-side prepared statements \(PREPARE/EXECUTE\) for performance optimization, which are session-level state stored on the PostgreSQL backend process. In PgBouncer's transaction pooling mode, each client transaction may be routed to a different backend connection from the pool. When the driver prepares a statement on Backend A during the first transaction, then tries to execute it on Backend B during the next transaction \(because the client was assigned a different backend\), the statement handle does not exist on Backend B, causing the error. The investigation involves checking PgBouncer logs and realizing the pooling mode is transaction. The fix requires either reconfiguring the database driver to disable prepared statements entirely \(accepting the slight performance cost of re-parsing SQL each time\), or switching PgBouncer to session pooling mode \(which assigns one backend connection per client connection for the duration of the client session, preserving session state including prepared statements, but reducing the scalability benefits of transaction pooling\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T03:01:46.809116+00:00— report_created — created