ERROR: prepared statement "s1" already exists (PgBouncer transaction mode)
Named prepared statements collided — typically because PgBouncer in transaction pooling mode hands connections between clients.
Seen on:
PostgreSQL
Meaning
In transaction mode, a client’s next transaction may run on a different server connection where its prepared statements don’t exist (or another client’s do). PgBouncer 1.21+ supports prepared statements with max_prepared_statements.
Common causes
- PgBouncer transaction pooling with drivers using named prepared statements
- Supabase/Neon poolers in transaction mode
⚡ Quick fix
- Upgrade PgBouncer and set max_prepared_statements
- Disable prepared statements in the driver (Prisma: ?pgbouncer=true; JDBC: prepareThreshold=0)
- Use session pooling for that client
Detailed fix by platform
PostgreSQL
postgresql://…@pooler:6543/db?pgbouncer=true
How to diagnose
- Pooler — Transaction mode?
- Driver — Uses named statements?
🧠 Still stuck? Analyze your error
Paste the full message, response headers or stack trace — we'll detect the platform and point to the most likely cause.
Was this page helpful?
Report a correction or suggest an improvement
Last updated 2 Oct 2026