golang-migrate/migrate · error

could not parse x-no-lock as bool: %w

Error message

could not parse x-no-lock as bool: %w

What it means

The MySQL driver accepts an optional x-no-lock custom parameter to disable the advisory migration lock. When this parameter is present and non-empty, it must parse as a Go bool via strconv.ParseBool (1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False); anything else makes Open return this wrapped error. It is raised inside Open before the database connection is used.

Source

Thrown at database/mysql/mysql.go:241

	return config, nil
}

func (m *Mysql) Open(url string) (database.Driver, error) {
	config, err := urlToMySQLConfig(url)
	if err != nil {
		return nil, err
	}

	customParams, err := extractCustomQueryParams(config)
	if err != nil {
		return nil, err
	}

	noLockParam, noLock := customParams["x-no-lock"], false
	if noLockParam != "" {
		noLock, err = strconv.ParseBool(noLockParam)
		if err != nil {
			return nil, fmt.Errorf("could not parse x-no-lock as bool: %w", err)
		}
	}

	statementTimeoutParam := customParams["x-statement-timeout"]
	statementTimeout := 0
	if statementTimeoutParam != "" {
		statementTimeout, err = strconv.Atoi(statementTimeoutParam)
		if err != nil {
			return nil, fmt.Errorf("could not parse x-statement-timeout as float: %w", err)
		}
	}

	db, err := sql.Open("mysql", config.FormatDSN())
	if err != nil {
		return nil, err
	}

	mx, err := WithInstance(db, &Config{

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Change the x-no-lock value to a strconv.ParseBool-compatible literal: true, false, 1, or 0
  2. Remove the x-no-lock parameter entirely if you want the default locking behavior (enabled)
  3. Normalize the value before building the URL if it comes from a config file or environment variable

Example fix

// before
url := "mysql://user:pass@tcp(db:3306)/app?x-no-lock=yes"
// after
url := "mysql://user:pass@tcp(db:3306)/app?x-no-lock=true"
Defensive patterns

Strategy: validation

Validate before calling

if v := params.Get("x-no-lock"); v != "" {
    if _, err := strconv.ParseBool(v); err != nil {
        return fmt.Errorf("x-no-lock must be a Go bool (true/false/1/0), got %q", v)
    }
}

Try / catch

drv, err := mysql.Open(dsn)
if err != nil && strings.Contains(err.Error(), "could not parse x-no-lock as bool") {
    return fmt.Errorf("fix x-no-lock in DSN to true/false/1/0: %w", err)
}

Prevention

When it happens

Trigger: Calling Open (or database.Open with a mysql:// URL) whose query string contains x-no-lock set to a value that is not a valid Go boolean, e.g. x-no-lock=yes, x-no-lock=on, or x-no-lock=1.0 (database/mysql/mysql.go:241-246).

Common situations: Developers assume YAML-style truthy values (yes/no/on/off) work; templating or CLI flags pass strings like 'enabled'; a copy-pasted Postgres driver param name collides with different conventions; quoting in the URL leaves stray characters.

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/e7705436ab87ca70. Report an issue: GitHub.