Incident brief
Bind message parameter mismatch
A Bind message in the extended query protocol supplied a different number of parameter values than the prepared statement expected. PostgreSQL rejected it as a protocol violation.
In 10 seconds
- What
- Bind message parameter mismatch
- What triggers it
- Prepare a query with one placeholder ($1) using psql's extended-protocol \bind meta-command.
- The fix
- Match the number of bound parameter values to the number of placeholders the statement actually declares.
- Proof
- Reproduced on PostgreSQL 16.14 → A Bind message supplying 2 parameter values for a statement with 1 placeholder was rejected with SQLSTATE 08P01. The identical statement with 1 value succeeded.
The fix
What to do right now
The immediate, application-level response to this error.
- Match the number of bound parameter values to the number of placeholders the statement actually declares.
- In a real client driver, this usually means fixing the parameter array passed to the prepared/parameterized query call.
SELECT $1::int \bind 5
\gDiagnose
See it live on the server
Run these against the affected instance to confirm the diagnosis before you act.
Standard triage — not specific to this error
These are canonical PostgreSQL system-catalog queries, shown as SQL to run. No sample output is attached because this is general triage, not a captured lab transcript.This SQLSTATE does not have an error-specific live snapshot yet. These are the canonical system-catalog queries you run against the affected server to see the problem in real time — standard triage, not a reproduced transcript.
What is running right now
Active backends, how long each has been running, and what it is waiting on.
SELECT pid,
state,
wait_event_type,
wait_event,
now() - query_start AS running_for,
left(query, 80) AS query
FROM pg_stat_activity
WHERE state <> 'idle'
AND pid <> pg_backend_pid()
ORDER BY running_for DESC NULLS LAST;Who is blocking whom
Turn raw blocking PIDs into the actual queries on both sides of the wait.
SELECT blocked.pid AS blocked_pid,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.query AS blocking_query
FROM pg_stat_activity AS blocked
JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS b(pid) ON true
JOIN pg_stat_activity AS blocking ON blocking.pid = b.pid
WHERE cardinality(pg_blocking_pids(blocked.pid)) > 0;Locks that are still waiting
Every lock a backend has requested but not yet been granted.
SELECT l.pid,
l.locktype,
l.mode,
l.granted,
COALESCE(c.relname, l.transactionid::text) AS object
FROM pg_locks l
LEFT JOIN pg_class c ON c.oid = l.relation
WHERE NOT l.granted
ORDER BY l.pid;Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual — not paraphrased.
PostgreSQL 16 Documentation — psql, \bind
\bind [ parameter ] ... Sets query parameters for the next query execution ... This command causes the extended query protocol ... to be used, unlike normal psql operation, which uses the simple query protocol.Read the full section on postgresql.org →
Bind with 2 values for 1 placeholder
The query has exactly one placeholder ($1), but the Bind message supplied two values — the server rejects this at the protocol level, before the query ever runs, as SQLSTATE 08P01.Bind with 1 value for 1 placeholder
With the parameter count corrected to match the one placeholder, the Bind message is valid and the query executes normally.Reproduce & verify
A real, single-session PostgreSQL reproduction using the extended query protocol
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab — the commands below are exactly what was executed.
- 1Prepare a query with one placeholder ($1) using psql's extended-protocol \bind meta-command.
- 2Supply two bound values instead of one.
- 3SQLSTATE 08P01 is reported: the Bind message doesn't match what the parsed statement requires.
One client: psql's \bind meta-command sends a real Bind message using the extended query protocol, not the ordinary simple query protocol psql normally uses.
-- No schema needed: this reproduces at the wire-protocol level.
SELECT 'no schema required' AS setup_note;SELECT $1::int \bind 1 2
\gSELECT $1::int \bind 5
\gWhat PostgreSQL actually returned
setup_note
--------------------
no schema required
(1 row)ERROR: bind message supplies 2 parameters, but prepared statement "" requires 1 int4
------
5
(1 row)The deeper lab audit for this error
What Pro unlocks here
- The exact prevention SQL — copy-paste ready
- Raw psql output captured from the Docker lab
- A senior-DBA action list to take it further
- Live monitoring queries to catch it in production
- The deeper audit: fix-that-fails counterexample, GUC before/after, server-log evidence
Related & next steps
Follow the thread
Everything this error touches — jump straight to the sibling error, term, runbook, or parameter.
Related errors
Verification
- Last verified
- 2026-07-16 (Docker lab, PostgreSQL 16.14)
- Reviewed by
- Verified against PostgreSQL 16.14 in an isolated lab environment
- Audit status
- reviewed