golang-migrate/migrate · error
x-migrations-table must be quoted (for instance '"migrate"."
Error message
x-migrations-table must be quoted (for instance '"migrate"."schema_migrations"') when x-migrations-table-quoted is enabled, current value is: %s
What it means
When `x-migrations-table-quoted=true` is set in the pgx DSN, the `x-migrations-table` value is used verbatim as a quoted SQL identifier, so it must start and end with a double quote (e.g. "migrate"."schema_migrations"). The library throws this error when quoting is enabled but the table name is not fully double-quoted, to prevent generating invalid SQL or silently using the wrong identifier.
Source
Thrown at database/pgx/pgx.go:188
// when making actual connection
// i.e. pgx://user:password@host:port/db => postgres://user:password@host:port/db
purl.Scheme = "postgres"
db, err := sql.Open("pgx/v4", 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)
if err != nil {
return nil, err
}
if multiStatementMaxSize <= 0 {View on GitHub (pinned to 01a9643f14)
Solutions
- Wrap the table name (and optional schema) in double quotes: x-migrations-table="migrate"."schema_migrations", URL-encoding quotes as %22 where needed.
- If you don't need a quoted identifier, set x-migrations-table-quoted=false or remove it and pass the plain table name.
- Verify the value after shell/env expansion — bash and YAML often strip inner double quotes; escape or single-quote appropriately.
- Confirm the first and last characters of the final string are both double quotes (the check is on the first and last byte).
Example fix
// before dsn := "postgres://user:pass@host/db?x-migrations-table=migrate.schema_migrations&x-migrations-table-quoted=true" // after dsn := "postgres://user:pass@host/db?x-migrations-table=%22migrate%22.%22schema_migrations%22&x-migrations-table-quoted=true"
Defensive patterns
Strategy: validation
Validate before calling
u, _ := url.Parse(dsn)
tbl := u.Query().Get("x-migrations-table")
quoted := u.Query().Get("x-migrations-table-quoted") == "true"
if quoted && tbl != "" && (tbl[0] != '"' || tbl[len(tbl)-1] != '"') {
return fmt.Errorf("x-migrations-table %q must be double-quoted when x-migrations-table-quoted=true", tbl)
} Try / catch
if err := m.Up(); err != nil {
if strings.Contains(err.Error(), "must be quoted") {
return fmt.Errorf("set x-migrations-table=\"schema\".\"table\" (URL-encode quotes as %%22): %w", err)
}
} Prevention
- URL-encode double quotes as %22 when embedding quoted identifiers in a DSN
- Only enable x-migrations-table-quoted when you actually need a case-sensitive/qualified table
- Watch for shells and YAML stripping literal double quotes from the value
When it happens
Trigger: A DSN like `postgres://...?x-migrations-table=migrate.schema_migrations&x-migrations-table-quoted=true` — the table value lacks surrounding double quotes, so Open returns this error before opening any migration session.
Common situations: Developers enabling the quoted option for a case-sensitive or schema-qualified migrations table but forgetting to add the quotes inside the URL value (remember the quotes must be URL-encoded as %22 in most cases); copying the non-quoted form from other driver docs; shell quoting stripping the literal double quotes.
Related errors
- unable to parse option x-multi-statement: %w
- "%s" MigrationsTable contains too many dot characters
- unable to parse option x-migrations-table-quoted: %w
- unknown lock strategy "%s"
- no database name
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/77b174a8fbde9b02.
Report an issue: GitHub.