{"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/c426bd93799de0f0e094c8f0582872c529d0ed0a/packets.go#L1029-L1065","documentation":"Returned by writeExecutePacket (packets.go:1047) when the number of arguments supplied to a prepared statement's Exec/Query does not equal stmt.paramCount, the number of '?' placeholders declared when the statement was prepared. The MySQL binary execute protocol requires an exact one-to-one mapping of arguments to placeholders.","triggerScenarios":"Calling stmt.Exec(a, b, c) on a statement prepared from SQL containing only two placeholders; building an argument slice dynamically and getting its length wrong; passing fewer args than placeholders.","commonSituations":"Adding or removing a '?' in the SQL without updating the argument list; an off-by-one when constructing a variadic args slice; copy-paste reuse of a statement with a different parameter count.","solutions":["Count the '?' placeholders in the prepared SQL and pass exactly that many arguments.","Construct the argument slice from a structured source and assert its length matches the placeholder count.","Add a unit test that verifies len(args) equals the expected placeholder count for each statement."],"exampleFix":"// before — 2 placeholders, 3 args\nstmt.Exec(ctx, \"a\", \"b\", \"c\")  // SQL: INSERT INTO t(x,y) VALUES(?,?)\n\n// after\nstmt.Exec(ctx, \"a\", \"b\")","handlingStrategy":"validation","validationCode":"expected := strings.Count(sqlText, \"?\") // adjust for literal '?' as needed\nif len(args) != expected {\n    return fmt.Errorf(\"expected %d arguments, got %d\", expected, len(args))\n}","typeGuard":null,"tryCatchPattern":"if _, err := stmt.Exec(args...); err != nil {\n    if strings.Contains(err.Error(), \"argument count mismatch\") {\n        // reconcile the number of '?' placeholders with the argument count\n    }\n}","preventionTips":["Keep the placeholder count and argument list in the same code block.","Assert argument counts in tests for every prepared statement.","Avoid dynamic SQL edits that change placeholder counts silently."],"tags":["prepared-statement","arguments","api-misuse"],"analyzedSha":"c426bd93799de0f0e094c8f0582872c529d0ed0a","analyzedAt":"2026-08-04T21:52:59.219Z","schemaVersion":2}