go-sql-driver/mysql · error
argument count mismatch
Error message
argument count mismatch (got: %d; has: %d)
What it means
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.
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.
Example fix
// before stmt.Exec(42, "extra") // SQL: INSERT INTO t(id) VALUES (?) // after stmt.Exec(42)
Defensive patterns
Strategy: validation
Validate before calling
// Count placeholders and assert against args before executing.
import "strings"
ph := strings.Count(query, "?")
if ph != len(args) {
return fmt.Errorf("expected %d args, got %d", ph, len(args))
} Type guard
null
Try / catch
// The mismatch is returned from Exec/Query; treat as a programmer error.
if _, err := stmt.Exec(args...); err != nil {
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Refactoring SQL changes the placeholder count but the Exec call is not updated; dynamic query construction; off-by-one in argument slicing.
Related errors
- cannot convert type: %T
- non-Value type %T returned from Value
- unsupported type %T, a
- unsupported type %T, a slice of
- can't convert %T to time.Time
AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07).
Data as JSON: /api/errors/5ac1e77291b4bb58.
Report an issue: GitHub.
Appendix: 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 03d76c7e07)