{"record":{"id":"fbd92cd27300ad60","repo":"golang-migrate/migrate","slug":"unable-to-parse-option-x-multi-statement-w-fbd92c","errorCode":null,"errorMessage":"unable to parse option x-multi-statement: %w","messagePattern":"unable to parse option x-multi-statement: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"database/postgres/postgres.go","lineNumber":199,"sourceCode":"\t\t}\n\t}\n\n\tmultiStatementMaxSize := DefaultMultiStatementMaxSize\n\tif s := purl.Query().Get(\"x-multi-statement-max-size\"); len(s) > 0 {\n\t\tmultiStatementMaxSize, err = strconv.Atoi(s)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif multiStatementMaxSize <= 0 {\n\t\t\tmultiStatementMaxSize = DefaultMultiStatementMaxSize\n\t\t}\n\t}\n\n\tmultiStatementEnabled := false\n\tif s := purl.Query().Get(\"x-multi-statement\"); len(s) > 0 {\n\t\tmultiStatementEnabled, err = strconv.ParseBool(s)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to parse option x-multi-statement: %w\", err)\n\t\t}\n\t}\n\n\tpx, err := WithInstance(db, &Config{\n\t\tDatabaseName:          purl.Path,\n\t\tMigrationsTable:       migrationsTable,\n\t\tMigrationsTableQuoted: migrationsTableQuoted,\n\t\tStatementTimeout:      time.Duration(statementTimeout) * time.Millisecond,\n\t\tMultiStatementEnabled: multiStatementEnabled,\n\t\tMultiStatementMaxSize: multiStatementMaxSize,\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn px, nil\n}","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/postgres/postgres.go#L181-L217","documentation":"Open() in the postgres driver reads the x-multi-statement URL parameter and parses it as a boolean with strconv.ParseBool. If the value is not a valid boolean literal (1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False), the underlying parse error is wrapped and returned. The driver cannot safely enable multi-statement mode from an unparseable value.","triggerScenarios":"Passing x-multi-statement=yes, x-multi-statement=on, or any other non-boolean string in a postgres:// URL passed to Open/New.","commonSituations":"Developers accustomed to other libraries' loose boolean parsing ('yes'/'on'/'1'/'enabled') set a truthy value that Go's ParseBool rejects; also happens when generating DSNs programmatically with unset variables producing text like '<nil>' or 'undefined'.","solutions":["Change the parameter to a Go-parseable boolean: true, false, 1, or 0","Remove the x-multi-statement parameter entirely if the default (false) is desired","Log the full DSN used and fix the code or env var that interpolates a non-boolean value"],"exampleFix":"// before\nurl := \"postgres://u:p@host/db?x-multi-statement=yes\"\n// after\nurl := \"postgres://u:p@host/db?x-multi-statement=true\"","handlingStrategy":"validation","validationCode":"v := dsn.Query().Get(\"x-multi-statement\")\nif v != \"\" {\n    if _, err := strconv.ParseBool(v); err != nil {\n        return fmt.Errorf(\"x-multi-statement must be a Go-parseable bool, got %q\", v)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember Go booleans are only 1/0/t/f/true/false — not yes/on/enabled","Interpolate booleans with strconv.FormatBool instead of string concatenation of raw config","Keep a DSN-builder helper that validates all x-* parameters before returning the URL"],"tags":["postgres","configuration","url-params","parsing"],"backgroundTag":"invalid-boolean-url-parameter","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}