vitessio/vitess · error
invalid parameter Number from client %v, statement: %v
Error message
invalid parameter Number from client %v, statement: %v
What it means
This error is returned when a MySQL client sends COM_STMT_SEND_LONG_DATA referencing a statement parameter ID that does not exist in the prepared statement (i.e., paramID >= number of declared parameters). The server rejects the packet and replies with an error packet to the client. It protects the protocol state from malformed or out-of-sync client packets.
Source
Thrown at go/mysql/conn.go:1315
func (c *Conn) handleComStmtSendLongData(data []byte) bool {
stmtID, paramID, chunk, ok := c.parseComStmtSendLongData(data)
c.recycleReadPacket()
if !ok {
err := fmt.Errorf("error parsing statement send long data from client %v, returning error: %v", c.ConnectionID, data)
return c.writeErrorPacketFromErrorAndLog(err)
}
prepare, ok := c.PrepareData[stmtID]
if !ok {
err := fmt.Errorf("got wrong statement id from client %v, statement ID(%v) is not found from record", c.ConnectionID, stmtID)
return c.writeErrorPacketFromErrorAndLog(err)
}
if prepare.BindVars == nil ||
prepare.ParamsCount == uint16(0) ||
paramID >= prepare.ParamsCount {
err := fmt.Errorf("invalid parameter Number from client %v, statement: %v", c.ConnectionID, prepare.PrepareStmt)
return c.writeErrorPacketFromErrorAndLog(err)
}
// COM_STMT_SEND_LONG_DATA is preparatory state for a later COM_STMT_EXECUTE,
// not a separately logged query. Hold its ingress bytes so COM_STMT_EXECUTE
// accounts for the full client payload used to run the statement.
if c.pendingLongDataIngressBytes == nil {
c.pendingLongDataIngressBytes = make(map[uint32]uint64)
}
c.pendingLongDataIngressBytes[stmtID] += c.currentCommandIngressBytes
key := fmt.Sprintf("v%d", paramID+1)
if val, ok := prepare.BindVars[key]; ok {
val.Value = append(val.Value, chunk...)
} else {
prepare.BindVars[key] = sqltypes.BytesBindVariable(chunk)
}
return trueView on GitHub (pinned to 01a25a7d17)
Solutions
- Check the client's statement SQL and confirm the number of `?` placeholders matches the highest parameter index the client sends long data for.
- Ensure COM_STMT_PREPARE succeeded before sending COM_STMT_SEND_LONG_DATA, and that COM_STMT_CLOSE has not been issued.
- Update or fix the client driver/library — modern mysql clients (go-sql-driver, Connector/J, etc.) compute param IDs correctly.
- If a proxy is in the path, verify it forwards COM_STMT_SEND_LONG_DATA for the correct statement handle without rewriting param IDs.
Example fix
// before: sending long data for an unknown param index // stmt has 2 placeholders, client sends paramID 2 sendLongData(stmtID, paramID=2, data) // after: align client params with the prepared statement // SELECT ? , ? -> valid paramIDs are 0 and 1 sendLongData(stmtID, paramID=1, data)
Defensive patterns
Strategy: validation
Validate before calling
// client side, before COM_STMT_SEND_LONG_DATA
if paramID < 0 || paramID >= numPlaceholders(stmtSQL) {
return fmt.Errorf("param %d out of range for statement with %d placeholders", paramID, numPlaceholders(stmtSQL))
} Try / catch
// server/driver side
if err := conn.Exec(stmt); err != nil {
if strings.Contains(err.Error(), "invalid parameter Number from client") {
// re-prepare the statement and rebind params before retrying
stmt, err = conn.Prepare(stmtSQL)
}
} Prevention
- Always complete COM_STMT_PREPARE before sending COM_STMT_SEND_LONG_DATA.
- Use a maintained client driver rather than hand-rolling COM_STMT_* packets.
- Re-prepare statements after schema/query changes instead of reusing stale statement handles.
- Count the `?` placeholders in the SQL and generate param IDs 0..n-1 only.
When it happens
Trigger: A client issues COM_STMT_SEND_LONG_DATA for a statement whose `prepare.BindVars` is nil or whose parameter index is >= `prepare.ParamsCount` — e.g. sending long data for param 3 on a statement prepared with only 2 placeholders, or sending long data after the statement was deallocated.
Common situations: Buggy or hand-rolled client drivers mishandling prepared-statement parameter numbering; client/server placeholder-count mismatch after application queries changed; stale connection reuse where the client thinks a statement is still prepared; proxies or load balancers desynchronizing COM_STMT_* streams.
Related errors
- got wrong statement id from client %v, statement ID(%v) is n
- unexpected: query ended without no results and no error
- no client certs for connection
- overflow
- mysqld >= 8.0.21 required to disable the redo log
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/b0eafffc78fb8656.
Report an issue: GitHub.