go-sql-driver/mysql · error
argument count mismatch (got: %d; has: %d)
Error message
argument count mismatch (got: %d; has: %d)
What it means
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.
Source
Thrown at packets.go:1047
// Send CMD packet
err := stmt.mc.writePacket(data[:4+pktLen])
// Every COM_LONG_DATA packet reset Packet Sequence
stmt.mc.resetSequence()
if err == nil {
data = data[pktLen-dataOffset:]
continue
}
return err
}
return nil
}
// Execute Prepared Statement
// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_stmt_execute.html
func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
if len(args) != stmt.paramCount {
return fmt.Errorf(
"argument count mismatch (got: %d; has: %d)",
len(args),
stmt.paramCount,
)
}
const minPktLen = 4 + 1 + 4 + 1 + 4
mc := stmt.mc
// Determine threshold dynamically to avoid packet size shortage.
longDataSize := max(mc.maxAllowedPacket/(stmt.paramCount+1), 64)
// Reset packet-sequence
mc.resetSequence()
var data []byte
var err error
View on GitHub (pinned to c426bd9379)
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.
Example fix
// before — 2 placeholders, 3 args stmt.Exec(ctx, "a", "b", "c") // SQL: INSERT INTO t(x,y) VALUES(?,?) // after stmt.Exec(ctx, "a", "b")
Defensive patterns
Strategy: validation
Validate before calling
expected := strings.Count(sqlText, "?") // adjust for literal '?' as needed
if len(args) != expected {
return fmt.Errorf("expected %d arguments, got %d", expected, len(args))
} Try / catch
if _, err := stmt.Exec(args...); err != nil {
if strings.Contains(err.Error(), "argument count mismatch") {
// reconcile the number of '?' placeholders with the argument count
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cannot convert type: %T
- invalid DATETIME packet length %d
- illegal %s length %d
- illegal %s packet length %d
- illegal TIME length %d
AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04).
Data as JSON: /data/errors/5ac1e77291b4bb58.json.
Report an issue: GitHub.