golang-migrate/migrate · error
unable to parse option x-migrations-table-quoted: %w
Error message
unable to parse option x-migrations-table-quoted: %w
What it means
Same validation as the pgx/v5 driver but in database/postgres (lib/pq path): Open parses the x-migrations-table-quoted URL option with strconv.ParseBool and wraps any parse failure with this message. The migration never reaches the database.
Source
Thrown at database/postgres/postgres.go:168
}
func (p *Postgres) Open(url string) (database.Driver, error) {
purl, err := nurl.Parse(url)
if err != nil {
return nil, err
}
db, err := sql.Open("postgres", migrate.FilterCustomQuery(purl).String())
if err != nil {
return nil, err
}
migrationsTable := purl.Query().Get("x-migrations-table")
migrationsTableQuoted := false
if s := purl.Query().Get("x-migrations-table-quoted"); len(s) > 0 {
migrationsTableQuoted, err = strconv.ParseBool(s)
if err != nil {
return nil, fmt.Errorf("unable to parse option x-migrations-table-quoted: %w", err)
}
}
if (len(migrationsTable) > 0) && (migrationsTableQuoted) && ((migrationsTable[0] != '"') || (migrationsTable[len(migrationsTable)-1] != '"')) {
return 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)
}
statementTimeoutString := purl.Query().Get("x-statement-timeout")
statementTimeout := 0
if statementTimeoutString != "" {
statementTimeout, err = strconv.Atoi(statementTimeoutString)
if err != nil {
return nil, err
}
}
multiStatementMaxSize := DefaultMultiStatementMaxSize
if s := purl.Query().Get("x-multi-statement-max-size"); len(s) > 0 {
multiStatementMaxSize, err = strconv.Atoi(s)View on GitHub (pinned to 01a9643f14)
Solutions
- Set the option to a ParseBool-valid literal: true, false, 1, 0, t, f, T, F, TRUE, FALSE, True, False
- Remove the parameter to accept the default (false)
- Percent-encode or single-quote the DSN so no spaces/invalid characters sneak into the value
- Confirm with the wrapped strconv error which raw string was rejected
Example fix
// before dsn := "postgres://u:p@host/db?x-migrations-table-quoted=enabled" // after dsn := "postgres://u:p@host/db?x-migrations-table-quoted=true"
Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(dsn)
if v := u.Query().Get("x-migrations-table-quoted"); v != "" {
if _, err := strconv.ParseBool(v); err != nil {
return fmt.Errorf("invalid x-migrations-table-quoted %q: %w", v, err)
}
} Type guard
func isParseBoolValue(v string) bool {
_, err := strconv.ParseBool(v)
return err == nil
} Try / catch
if err := openMigrations(); err != nil {
if strings.Contains(err.Error(), "unable to parse option x-migrations-table-quoted") {
log.Fatalf("use true/false (or 1/0) for x-migrations-table-quoted: %v", err)
}
panic(err)
} Prevention
- Restrict DSN booleans to Go's ParseBool literals
- Trim and sanitize DSN strings sourced from env vars/config files
- Add a startup check that parses all x-* query options before migrate.Open
When it happens
Trigger: postgres.Open (or the registered database/sql driver 'postgres' via sql.Open + migrate) with a URL like postgres://u:p@host/db?x-migrations-table-quoted=enabled or containing whitespace in the value.
Common situations: Hand-editing DSN strings, config templates emitting 'True' with trailing spaces or 'yes', mixing up this option with another library's boolean syntax, URL-encoding issues leaving %20 in the value.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unable to parse option x-migrations-table-quoted: %w
- unable to parse option x-multi-statement: %w
- no database name
- x-migrations-table must be quoted (for instance '"migrate"."
- unable to parse option x-multi-statement: %w
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/8572eae31727b3dd.
Report an issue: GitHub.