{"record":{"id":"b0eafffc78fb8656","repo":"vitessio/vitess","slug":"invalid-parameter-number-from-client-v-statement","errorCode":null,"errorMessage":"invalid parameter Number from client %v, statement: %v","messagePattern":"invalid parameter Number from client (.+?), statement: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/conn.go","lineNumber":1315,"sourceCode":"\nfunc (c *Conn) handleComStmtSendLongData(data []byte) bool {\n\tstmtID, paramID, chunk, ok := c.parseComStmtSendLongData(data)\n\tc.recycleReadPacket()\n\tif !ok {\n\t\terr := fmt.Errorf(\"error parsing statement send long data from client %v, returning error: %v\", c.ConnectionID, data)\n\t\treturn c.writeErrorPacketFromErrorAndLog(err)\n\t}\n\n\tprepare, ok := c.PrepareData[stmtID]\n\tif !ok {\n\t\terr := fmt.Errorf(\"got wrong statement id from client %v, statement ID(%v) is not found from record\", c.ConnectionID, stmtID)\n\t\treturn c.writeErrorPacketFromErrorAndLog(err)\n\t}\n\n\tif prepare.BindVars == nil ||\n\t\tprepare.ParamsCount == uint16(0) ||\n\t\tparamID >= prepare.ParamsCount {\n\t\terr := fmt.Errorf(\"invalid parameter Number from client %v, statement: %v\", c.ConnectionID, prepare.PrepareStmt)\n\t\treturn c.writeErrorPacketFromErrorAndLog(err)\n\t}\n\n\t// COM_STMT_SEND_LONG_DATA is preparatory state for a later COM_STMT_EXECUTE,\n\t// not a separately logged query. Hold its ingress bytes so COM_STMT_EXECUTE\n\t// accounts for the full client payload used to run the statement.\n\tif c.pendingLongDataIngressBytes == nil {\n\t\tc.pendingLongDataIngressBytes = make(map[uint32]uint64)\n\t}\n\tc.pendingLongDataIngressBytes[stmtID] += c.currentCommandIngressBytes\n\n\tkey := fmt.Sprintf(\"v%d\", paramID+1)\n\tif val, ok := prepare.BindVars[key]; ok {\n\t\tval.Value = append(val.Value, chunk...)\n\t} else {\n\t\tprepare.BindVars[key] = sqltypes.BytesBindVariable(chunk)\n\t}\n\treturn true","sourceCodeStart":1297,"sourceCodeEnd":1333,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/conn.go#L1297-L1333","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: sending long data for an unknown param index\n// stmt has 2 placeholders, client sends paramID 2\nsendLongData(stmtID, paramID=2, data)\n\n// after: align client params with the prepared statement\n// SELECT ? , ? -> valid paramIDs are 0 and 1\nsendLongData(stmtID, paramID=1, data)","handlingStrategy":"validation","validationCode":"// client side, before COM_STMT_SEND_LONG_DATA\nif paramID < 0 || paramID >= numPlaceholders(stmtSQL) {\n    return fmt.Errorf(\"param %d out of range for statement with %d placeholders\", paramID, numPlaceholders(stmtSQL))\n}","typeGuard":null,"tryCatchPattern":"// server/driver side\nif err := conn.Exec(stmt); err != nil {\n    if strings.Contains(err.Error(), \"invalid parameter Number from client\") {\n        // re-prepare the statement and rebind params before retrying\n        stmt, err = conn.Prepare(stmtSQL)\n    }\n}","preventionTips":["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."],"tags":["mysql","prepared-statements","protocol","client-error"],"backgroundTag":"prepared-statement-parameter-mismatch","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}