{"record":{"id":"e7705436ab87ca70","repo":"golang-migrate/migrate","slug":"could-not-parse-x-no-lock-as-bool-w","errorCode":null,"errorMessage":"could not parse x-no-lock as bool: %w","messagePattern":"could not parse x-no-lock as bool: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"database/mysql/mysql.go","lineNumber":241,"sourceCode":"\treturn config, nil\n}\n\nfunc (m *Mysql) Open(url string) (database.Driver, error) {\n\tconfig, err := urlToMySQLConfig(url)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcustomParams, err := extractCustomQueryParams(config)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tnoLockParam, noLock := customParams[\"x-no-lock\"], false\n\tif noLockParam != \"\" {\n\t\tnoLock, err = strconv.ParseBool(noLockParam)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not parse x-no-lock as bool: %w\", err)\n\t\t}\n\t}\n\n\tstatementTimeoutParam := customParams[\"x-statement-timeout\"]\n\tstatementTimeout := 0\n\tif statementTimeoutParam != \"\" {\n\t\tstatementTimeout, err = strconv.Atoi(statementTimeoutParam)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"could not parse x-statement-timeout as float: %w\", err)\n\t\t}\n\t}\n\n\tdb, err := sql.Open(\"mysql\", config.FormatDSN())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tmx, err := WithInstance(db, &Config{","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/mysql/mysql.go#L223-L259","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Change the x-no-lock value to a strconv.ParseBool-compatible literal: true, false, 1, or 0","Remove the x-no-lock parameter entirely if you want the default locking behavior (enabled)","Normalize the value before building the URL if it comes from a config file or environment variable"],"exampleFix":"// before\nurl := \"mysql://user:pass@tcp(db:3306)/app?x-no-lock=yes\"\n// after\nurl := \"mysql://user:pass@tcp(db:3306)/app?x-no-lock=true\"","handlingStrategy":"validation","validationCode":"if v := params.Get(\"x-no-lock\"); v != \"\" {\n    if _, err := strconv.ParseBool(v); err != nil {\n        return fmt.Errorf(\"x-no-lock must be a Go bool (true/false/1/0), got %q\", v)\n    }\n}","typeGuard":null,"tryCatchPattern":"drv, err := mysql.Open(dsn)\nif err != nil && strings.Contains(err.Error(), \"could not parse x-no-lock as bool\") {\n    return fmt.Errorf(\"fix x-no-lock in DSN to true/false/1/0: %w\", err)\n}","preventionTips":["Only use strconv.ParseBool-accepted values: true/false/1/0 (not yes/no/on/off)","Normalize config values with a helper before interpolating into the DSN","Add a unit test that builds the DSN from your config"],"tags":["mysql","configuration","boolean-parsing","url-parameters"],"backgroundTag":"invalid-boolean-parameter","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}