{"record":{"id":"5ac1e77291b4bb58","repo":"go-sql-driver/mysql","slug":"argument-count-mismatch-got-d-has-d","errorCode":null,"errorMessage":"argument count mismatch (got: %d; has: %d)","messagePattern":"argument count mismatch \\(got: (.+?); has: (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packets.go","lineNumber":1047,"sourceCode":"\t\t// Send CMD packet\n\t\terr := stmt.mc.writePacket(data[:4+pktLen])\n\t\t// Every COM_LONG_DATA packet reset Packet Sequence\n\t\tstmt.mc.resetSequence()\n\t\tif err == nil {\n\t\t\tdata = data[pktLen-dataOffset:]\n\t\t\tcontinue\n\t\t}\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// Execute Prepared Statement\n// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_stmt_execute.html\nfunc (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {\n\tif len(args) != stmt.paramCount {\n\t\treturn fmt.Errorf(\n\t\t\t\"argument count mismatch (got: %d; has: %d)\",\n\t\t\tlen(args),\n\t\t\tstmt.paramCount,\n\t\t)\n\t}\n\n\tconst minPktLen = 4 + 1 + 4 + 1 + 4\n\tmc := stmt.mc\n\n\t// Determine threshold dynamically to avoid packet size shortage.\n\tlongDataSize := max(mc.maxAllowedPacket/(stmt.paramCount+1), 64)\n\n\t// Reset packet-sequence\n\tmc.resetSequence()\n\n\tvar data []byte\n\tvar err error\n","sourceCodeStart":1029,"sourceCodeEnd":1065,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/03d76c7e07908e255ce62d126d07ede3f2365d86/packets.go#L1029-L1065","documentation":"writeExecutePacket compares the number of supplied arguments against the prepared statement's parameter count (stmt.paramCount, returned by the server when the statement was prepared). A mismatch means the number of '?' placeholders differs from the arguments passed to Exec.","triggerScenarios":"Calling stmt.Exec with the wrong number of args, e.g. stmt.Exec(1,2) for \"INSERT INTO t VALUES (?)\", or passing fewer args than placeholders.","commonSituations":"Refactoring SQL changes the placeholder count but the Exec call is not updated; dynamic query construction; off-by-one in argument slicing.","solutions":["Align the number of Exec/Query arguments with the number of '?' placeholders in the SQL.","Use a helper that counts placeholders and asserts against len(args) before Exec.","When SQL changes, update the call site in the same commit."],"exampleFix":"// before\nstmt.Exec(42, \"extra\") // SQL: INSERT INTO t(id) VALUES (?)\n// after\nstmt.Exec(42)","handlingStrategy":"validation","validationCode":"// Count placeholders and assert against args before executing.\nimport \"strings\"\nph := strings.Count(query, \"?\")\nif ph != len(args) {\n    return fmt.Errorf(\"expected %d args, got %d\", ph, len(args))\n}","typeGuard":"null","tryCatchPattern":"// The mismatch is returned from Exec/Query; treat as a programmer error.\nif _, err := stmt.Exec(args...); err != nil {\n    return err\n}","preventionTips":["Count '?' placeholders and compare to len(args) in a helper.","Keep SQL and its Exec call in the same review scope.","Use query builders that track parameter counts."],"tags":["go","mysql","prepared-statement","sql"],"backgroundTag":null,"analyzedSha":"03d76c7e07908e255ce62d126d07ede3f2365d86","analyzedAt":"2026-08-07T10:39:17.340Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}