prepared statement exists 🐘 PostgreSQL

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

  1. Upgrade PgBouncer and set max_prepared_statements
  2. Disable prepared statements in the driver (Prisma: ?pgbouncer=true; JDBC: prepareThreshold=0)
  3. Use session pooling for that client

Detailed fix by platform

PostgreSQL

  1. postgresql://…@pooler:6543/db?pgbouncer=true

How to diagnose

  1. Pooler — Transaction mode?
  2. 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.