go-sql-driver/mysql · error
mysql: driver does not support the use of Named Parameters
Error message
mysql: driver does not support the use of Named Parameters
What it means
Returned by namedValueToValue (utils.go:785) when any driver.NamedValue passed to Exec/Query carries a non-empty Name. go-sql-driver only supports positional '?' placeholders; it does not implement named-parameter binding (tracked as issue #561). Called from QueryContext/ExecContext on both mysqlConn and mysqlStmt (connection.go:637,656,690,709).
Solutions
- Use positional '?' placeholders and pass args in the matching order.
- If you have a name->value map, expand it to an ordered slice yourself before calling the driver.
- Switch to a layer that rewrites named params to positional (some query builders do this), or pre-process the SQL.
- Do not use sql.Named with this driver.
Example fix
// before: named parameter -> error
rows, err := db.Query("SELECT * FROM t WHERE id=:id", sql.Named("id", 7))
// after: positional placeholder
rows, err := db.Query("SELECT * FROM t WHERE id=?", 7) Defensive patterns
Strategy: validation
Validate before calling
// Reject named args up front and translate maps to positional slices.
func toPositional(query string, named map[string]any, order []string) (string, []any) {
args := make([]any, len(order))
for i, k := range order { args[i] = named[k] }
return query, args // query must already use '?' placeholders
} Type guard
func isNamedParamRejected(err error) bool {
return err != nil && strings.Contains(err.Error(), "Named Parameters")
} Try / catch
if isNamedParamRejected(err) {
// rewrite to positional '?' + ordered args, then retry.
} Prevention
- Use '?' placeholders and positional args with this driver.
- Never pass sql.Named(...) to db.Exec/Query/Stmt methods.
- Configure query builders to emit positional placeholders for MySQL.
When it happens
Trigger: Calling db.QueryContext/db.ExecContext (or stmt equivalents) with arguments built via sql.Named("name", value), or any []driver.NamedValue where param.Name != "".
Common situations: Porting code from a driver that supports @name/:name binds; using an ORM/query builder that emits sql.Named by default; mixing named-style calls into a MySQL codebase.
AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07).
Data as JSON: /api/errors/51243cad227a1492.
Report an issue: GitHub.
Appendix: source
Thrown at utils.go:785
func (ae *atomicError) Set(value error) {
ae.value.Store(value)
}
// Value returns the current error value
func (ae *atomicError) Value() error {
if v := ae.value.Load(); v != nil {
// this will panic if the value doesn't implement the error interface
return v.(error)
}
return nil
}
func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
dargs := make([]driver.Value, len(named))
for n, param := range named {
if len(param.Name) > 0 {
// TODO: support the use of Named Parameters #561
return nil, errors.New("mysql: driver does not support the use of Named Parameters")
}
dargs[n] = param.Value
}
return dargs, nil
}
func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
switch sql.IsolationLevel(level) {
case sql.LevelRepeatableRead:
return "REPEATABLE READ", nil
case sql.LevelReadCommitted:
return "READ COMMITTED", nil
case sql.LevelReadUncommitted:
return "READ UNCOMMITTED", nil
case sql.LevelSerializable:
return "SERIALIZABLE", nil
default:
return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)View on GitHub (pinned to 03d76c7e07)