{"record":{"id":"7eaacb300fe458e2","repo":"vitessio/vitess","slug":"got-wrong-statement-id-from-client-v-statement-i","errorCode":null,"errorMessage":"got wrong statement id from client %v, statement ID(%v) is not found from record","messagePattern":"got wrong statement id from client (.+?), statement ID\\((.+?)\\) is not found from record","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/conn.go","lineNumber":1308,"sourceCode":"\n\tif err := c.writeOKPacket(&PacketOK{statusFlags: c.StatusFlags}); err != nil {\n\t\tlog.Error(fmt.Sprintf(\"Error writing ComStmtReset OK packet to client %v: %v\", c.ConnectionID, err))\n\t\treturn false\n\t}\n\treturn true\n}\n\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","sourceCodeStart":1290,"sourceCodeEnd":1326,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/conn.go#L1290-L1326","documentation":"A MySQL client sent a COM_STMT_SEND_LONG_DATA packet referencing a statement id that the server has no prepared-statement record for, so conn.go rejects it with this error and returns an error packet. It indicates the client's statement id does not match anything registered during COM_STMT_PREPARE — a client/server prepared-statement bookkeeping desync.","triggerScenarios":"Client sends COM_STMT_SEND_LONG_DATA with stmtID not present in c.PrepareData — after the statement was closed (COM_STMT_CLOSE), never prepared on this connection, or a stale/reused id from a previous connection state.","commonSituations":"Client driver bugs or connection reuse after reset where prepared-statement ids are recycled; proxies/multiplexers replaying packets on a new connection; applications using mysql_stmt_send_long_data on statements closed earlier due to an error.","solutions":["Check the client driver/library version for known prepared-statement bugs and upgrade it","Ensure the application prepares the statement on this same connection before sending long data and does not close it prematurely","Disable client-side prepared-statement caching / reset connections cleanly (e.g. useCHARSET/reset settings) to avoid stale ids","Inspect proxy/middleware in the path that may drop COM_STMT_PREPARE state"],"exampleFix":"// before: driver reuses stmt id after connection reset\nstmt.SendLongData(id, param, data)\n// after: re-prepare on new connection before sending\nstmt := conn.Prepare(query)\nstmt.SendLongData(id, param, data)","handlingStrategy":"try-catch","validationCode":"// client-side: only send long data for ids returned by the last PREPARE on this connection\nif stmtID < 1 || stmtID > lastPrepareID(conn) { skipSend() }","typeGuard":"func statementKnown(conn *mysql.Conn, stmtID uint32) bool {\n\t_, ok := conn.PrepareData[stmtID]\n\treturn ok\n}","tryCatchPattern":"if err := c.handleStatementSendLongData(stmtID, ...); err != nil {\n\t// returns ERR packet to client; log connection id + stmtID for driver debugging\n\treturn c.writeErrorPacketFromErrorAndLog(err)\n}","preventionTips":["Keep prepared statements and their ids per-connection; never share across connections","Re-prepare statements after reconnects or connection resets","Upgrade MySQL client drivers with known COM_STMT_SEND_LONG_DATA bugs","Avoid proxies that drop COM_STMT_PREPARE packets while forwarding others"],"tags":["mysql","protocol","prepared-statements"],"backgroundTag":"unknown-statement-id","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}