golang-migrate/migrate · error
unable to parse option x-multi-statement: %w
Error message
unable to parse option x-multi-statement: %w
What it means
The x-multi-statement URL option for the pgx/v5 driver enables multiple SQL statements per migration. Its value is parsed with strconv.ParseBool, and Open fails with this error if the value is not a recognized boolean literal. Purely a client-side URL validation failure.
Source
Thrown at database/pgx/v5/pgx.go:191
}
}
multiStatementMaxSize := DefaultMultiStatementMaxSize
if s := purl.Query().Get("x-multi-statement-max-size"); len(s) > 0 {
multiStatementMaxSize, err = strconv.Atoi(s)
if err != nil {
return nil, err
}
if multiStatementMaxSize <= 0 {
multiStatementMaxSize = DefaultMultiStatementMaxSize
}
}
multiStatementEnabled := false
if s := purl.Query().Get("x-multi-statement"); len(s) > 0 {
multiStatementEnabled, err = strconv.ParseBool(s)
if err != nil {
return nil, fmt.Errorf("unable to parse option x-multi-statement: %w", err)
}
}
px, err := WithInstance(db, &Config{
DatabaseName: purl.Path,
MigrationsTable: migrationsTable,
MigrationsTableQuoted: migrationsTableQuoted,
StatementTimeout: time.Duration(statementTimeout) * time.Millisecond,
MultiStatementEnabled: multiStatementEnabled,
MultiStatementMaxSize: multiStatementMaxSize,
})
if err != nil {
return nil, err
}
return px, nil
}View on GitHub (pinned to 01a9643f14)
Solutions
- Use a valid ParseBool value: true/false (or 1/0, t/f, T/F, TRUE/FALSE)
- Remove x-multi-statement from the URL if multi-statement behavior is not needed (it defaults to false)
- Trim whitespace around the value — ' true' is not parseable
- Inspect the wrapped strconv error for the exact offending string
Example fix
// before dsn := "postgres://u:p@host/db?x-multi-statement=on" // after dsn := "postgres://u:p@host/db?x-multi-statement=true"
Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(dsn)
if v := u.Query().Get("x-multi-statement"); v != "" {
if _, err := strconv.ParseBool(v); err != nil {
return fmt.Errorf("invalid x-multi-statement %q: %w", v, err)
}
} Type guard
func isValidBool(v string) bool {
_, err := strconv.ParseBool(v)
return err == nil
} Try / catch
if err := m.Up(); err != nil {
if strings.Contains(err.Error(), "unable to parse option x-multi-statement") {
log.Fatalf("DSN x-multi-statement must be a boolean literal: %v", err)
}
panic(err)
} Prevention
- Use true/false, never yes/on/enabled, for Go DSN boolean options
- Centralize DSN construction in a helper that appends validated options
- Validate all x-* options before handing the DSN to migrate
When it happens
Trigger: Opening a pgx/v5 connection with a URL like postgres://user:pass@host/db?x-multi-statement=yes, =1.0, or any non-boolean string in x-multi-statement.
Common situations: Copying the option name but inventing the value ('yes', 'on'), templating engines injecting an empty or malformed value, or accidental duplication of the query parameter producing a concatenated string.
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-migrations-table-quoted: %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/f2b8aa09ae1e84e1.
Report an issue: GitHub.