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` pgx DSN option enables multi-statement migration files (with `x-multi-statement-max-size` bounding the batch size). This error is wrapped from strconv.ParseBool when the option's value cannot be parsed as a Go boolean, and Open aborts before connecting to the database.

Source

Thrown at database/pgx/pgx.go:215

		}
	}

	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)
		}
	}

	lockStrategy := purl.Query().Get("x-lock-strategy")
	lockTable := purl.Query().Get("x-lock-table")

	px, err := WithInstance(db, &Config{
		DatabaseName:          purl.Path,
		MigrationsTable:       migrationsTable,
		MigrationsTableQuoted: migrationsTableQuoted,
		StatementTimeout:      time.Duration(statementTimeout) * time.Millisecond,
		MultiStatementEnabled: multiStatementEnabled,
		MultiStatementMaxSize: multiStatementMaxSize,
		LockStrategy:          lockStrategy,
		LockTable:             lockTable,
	})

	if err != nil {

View on GitHub (pinned to 01a9643f14)

Solutions

  1. Set the value to a strconv.ParseBool-accepted string: true/false, 1/0, t/f, T/F, TRUE/FALSE, True/False.
  2. Remove the parameter if multi-statement support is not needed (defaults to false).
  3. Log the final DSN after config substitution and confirm the parameter is intact (no spaces, correct URL encoding).
  4. Normalize application-level booleans (yes/no/on/off) to Go booleans before composing the migrate URL.

Example fix

// before
dsn := "postgres://user:pass@host/db?x-multi-statement=enable"
// after
dsn := "postgres://user:pass@host/db?x-multi-statement=true"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(dsn)
if err != nil { return err }
if v := u.Query().Get("x-multi-statement"); v != "" {
    if _, err := strconv.ParseBool(v); err != nil {
        return fmt.Errorf("x-multi-statement must be a Go boolean, got %q", v)
    }
}

Type guard

func isValidGoBool(s string) bool { _, err := strconv.ParseBool(s); return err == nil }

Try / catch

drv, err := pgx.Open(dsn)
if err != nil && strings.Contains(err.Error(), "unable to parse option x-multi-statement") {
    return fmt.Errorf("x-multi-statement accepts only true/false/1/0/t/f: %w", err)
}

Prevention

When it happens

Trigger: Calling pgx.Open with a DSN containing `x-multi-statement=<invalid>`, e.g. `x-multi-statement=enable`, `x-multi-statement=1 ` with a trailing space, `x-multi-statement=yes`, or a value mangled by URL encoding/templating.

Common situations: Enabling multi-statement migrations for MySQL-style SQL files against Postgres and typing non-Go boolean values; env-var substitution inserting an empty or malformed value; copying examples from other tools that accept on/off or yes/no.

Understand the failure class

Related errors


AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02). Data as JSON: /api/errors/c381150b1f86cba7. Report an issue: GitHub.