{"record":{"id":"894ec4f8bf10abbd","repo":"golang-migrate/migrate","slug":"unable-to-parse-option-x-migrations-table-quoted","errorCode":null,"errorMessage":"unable to parse option x-migrations-table-quoted: %w","messagePattern":"unable to parse option x-migrations-table-quoted: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"database/pgx/pgx.go","lineNumber":184,"sourceCode":"\t\treturn nil, err\n\t}\n\n\t// Driver is registered as pgx, but connection string must use postgres schema\n\t// when making actual connection\n\t// i.e. pgx://user:password@host:port/db => postgres://user:password@host:port/db\n\tpurl.Scheme = \"postgres\"\n\n\tdb, err := sql.Open(\"pgx/v4\", migrate.FilterCustomQuery(purl).String())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tmigrationsTable := purl.Query().Get(\"x-migrations-table\")\n\tmigrationsTableQuoted := false\n\tif s := purl.Query().Get(\"x-migrations-table-quoted\"); len(s) > 0 {\n\t\tmigrationsTableQuoted, err = strconv.ParseBool(s)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to parse option x-migrations-table-quoted: %w\", err)\n\t\t}\n\t}\n\tif (len(migrationsTable) > 0) && (migrationsTableQuoted) && ((migrationsTable[0] != '\"') || (migrationsTable[len(migrationsTable)-1] != '\"')) {\n\t\treturn nil, fmt.Errorf(\"x-migrations-table must be quoted (for instance '\\\"migrate\\\".\\\"schema_migrations\\\"') when x-migrations-table-quoted is enabled, current value is: %s\", migrationsTable)\n\t}\n\n\tstatementTimeoutString := purl.Query().Get(\"x-statement-timeout\")\n\tstatementTimeout := 0\n\tif statementTimeoutString != \"\" {\n\t\tstatementTimeout, err = strconv.Atoi(statementTimeoutString)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\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)","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/pgx/pgx.go#L166-L202","documentation":"The pgx driver in golang-migrate accepts a boolean DSN query parameter `x-migrations-table-quoted` that controls whether the migrations table name is treated as a quoted (case-sensitive, possibly schema-qualified) SQL identifier. This error is wrapped from strconv.ParseBool when the value of that query parameter is not a valid boolean string (\"1\", \"t\", \"true\", \"0\", \"f\", \"false\"). The library throws it during Open to fail fast on an unparseable connection URL option.","triggerScenarios":"Calling pgx.Open or pgxv5.WithInstance (via Open) with a DSN whose query string contains `x-migrations-table-quoted=<something>` where <something> is not a strconv.ParseBool-compatible value, e.g. `x-migrations-table-quoted=yes`, `x-migrations-table-quoted=on`, `x-migrations-table-quoted=TRUE ` with whitespace, or `x-migrations-table-quoted=` followed by typos.","commonSituations":"Developers copying PostgreSQL-style boolean syntax (on/off, yes/no) into the migrate DSN; templated config files substituting YAML/JSON booleans (true/false is fine, but Yes/On is not); URL-encoding issues that mangle the value; mixing documentation for other drivers into the pgx DSN.","solutions":["Change the x-migrations-table-quoted value to a Go-parseable boolean: 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.","Remove the x-migrations-table-quoted parameter entirely if you do not need a quoted migrations table identifier (it defaults to false).","Print/log the DSN before passing to Open and verify no templating or environment substitution corrupted the value (watch for stray spaces or encoding).","If your config layer produces non-Go booleans (e.g. yes/no), normalize them before building the migrate URL."],"exampleFix":"// before\ndsn := \"postgres://user:pass@host/db?x-migrations-table-quoted=yes\"\n// after\ndsn := \"postgres://user:pass@host/db?x-migrations-table-quoted=true\"","handlingStrategy":"validation","validationCode":"// validate DSN option before pgx.Open\nu, err := url.Parse(dsn)\nif err != nil { return err }\nif v := u.Query().Get(\"x-migrations-table-quoted\"); v != \"\" {\n    if _, err := strconv.ParseBool(v); err != nil {\n        return fmt.Errorf(\"x-migrations-table-quoted must be a Go boolean (true/false/1/0/t/f), got %q\", v)\n    }\n}","typeGuard":"func isValidGoBool(s string) bool { _, err := strconv.ParseBool(s); return err == nil }","tryCatchPattern":"drv, err := pgx.Open(dsn)\nif errors.Is(err, ...) || strings.Contains(err.Error(), \"unable to parse option x-migrations-table-quoted\") {\n    return fmt.Errorf(\"fix DSN: x-migrations-table-quoted accepts only Go booleans: %w\", err)\n}","preventionTips":["Only ever write true/false or 1/0 for x-* boolean DSN options","Build the migrate DSN from typed booleans via url.Values, not string templates","Add a unit test that parses every composed DSN with url.ParseQuery"],"tags":["postgresql","config","parsing","url-options"],"backgroundTag":"invalid-boolean-config-option","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}