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

Thrown by namedValueToValue (utils.go:785) when any element of the parameter slice has a non-empty Name — i.e. the caller passed sql.Named(...) / named parameters. The go-sql-driver explicitly does not implement named parameters (tracked as issue #561); database/sql normally strips names before calling the driver, so reaching this branch means named args leaked through to the driver level.

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 c426bd9379)

Solutions

  1. Replace sql.Named("x", v) with a positional '?' placeholder and pass v positionally.
  2. If you have a map of named params, convert them to positional '?' in the same order you pass the values.
  3. Switch to a query builder that emits positional placeholders for MySQL, or pre-process the SQL to substitute names.
  4. Do not rely on @name/:name support — this driver documents it as unsupported.

Example fix

// before
db.Exec("INSERT INTO t(a,b) VALUES(:a,:b)", sql.Named("a", 1), sql.Named("b", 2))

// after
db.Exec("INSERT INTO t(a,b) VALUES(?,?)", 1, 2)
Defensive patterns

Strategy: validation

Validate before calling

// reject named params before they reach the driver
func positionalArgs(query string, args []any) (string, []any, error) {
    var out []any
    for _, a := range args {
        if nv, ok := a.(driver.NamedValue); ok && nv.Name != "" {
            return "", nil, errors.New("named parameters not supported by mysql driver")
        }
        if named, ok := a.(sql.NamedArg); ok {
            return "", nil, fmt.Errorf("named parameter %q not supported", named.Name)
        }
        out = append(out, a)
    }
    return query, out, nil
}

Type guard

// hasNamedArg detects sql.NamedArg / named values before exec
func hasNamedArg(args []any) bool {
    for _, a := range args {
        if _, ok := a.(sql.NamedArg); ok {
            return true
        }
    }
    return false
}

Prevention

When it happens

Trigger: Calling db.Exec/Query with an argument built by sql.Named("col", val) or a struct expansion that yields named args, in a code path where database/sql did not (or could not) map names to positional placeholders. The driver rejects the first named arg it sees.

Common situations: Using a query builder / ORM that emits @name or :name parameters with this driver; passing sql.Named directly; upgrading from a driver that supported named params to this one; using a high-level helper that always names its args.

Related errors


AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04). Data as JSON: /data/errors/51243cad227a1492.json. Report an issue: GitHub.