golang-migrate/migrate · error
unknown lock strategy "%s"
Error message
unknown lock strategy "%s"
What it means
Postgres.Lock acquires a migration lock using the configured LockStrategy. This error is returned from the default branch of the strategy switch when p.config.LockStrategy is neither the advisory-lock nor table-lock strategy, meaning the strategy value is empty or unrecognized.
Source
Thrown at database/pgx/pgx.go:257
func (p *Postgres) Close() error {
connErr := p.conn.Close()
dbErr := p.db.Close()
if connErr != nil || dbErr != nil {
return fmt.Errorf("conn: %v, db: %v", connErr, dbErr)
}
return nil
}
func (p *Postgres) Lock() error {
return database.CasRestoreOnErr(&p.isLocked, false, true, database.ErrLocked, func() error {
switch p.config.LockStrategy {
case LockStrategyAdvisory:
return p.applyAdvisoryLock()
case LockStrategyTable:
return p.applyTableLock()
default:
return fmt.Errorf("unknown lock strategy \"%s\"", p.config.LockStrategy)
}
})
}
func (p *Postgres) Unlock() error {
return database.CasRestoreOnErr(&p.isLocked, true, false, database.ErrNotLocked, func() error {
switch p.config.LockStrategy {
case LockStrategyAdvisory:
return p.releaseAdvisoryLock()
case LockStrategyTable:
return p.releaseTableLock()
default:
return fmt.Errorf("unknown lock strategy \"%s\"", p.config.LockStrategy)
}
})
}
// https://www.postgresql.org/docs/9.6/static/explicit-locking.html#ADVISORY-LOCKSView on GitHub (pinned to 01a9643f14)
Solutions
- Set LockStrategy to a defined constant: pgx.LockStrategyAdvisory or pgx.LockStrategyTable.
- Leave LockStrategy zero/unset only if the library's defaults apply; otherwise always assign a constant, never a raw string.
- Print the config value and compare against the exported LockStrategy constants to catch typos.
- If accepting user input, validate/parse it into a valid LockStrategy before constructing Config.
Example fix
// before
cfg := &pgx.Config{MigrationsTable: "schema_migrations", LockStrategy: "advisory"}
// after
cfg := &pgx.Config{MigrationsTable: "schema_migrations", LockStrategy: pgx.LockStrategyAdvisory} Defensive patterns
Strategy: validation
Validate before calling
func validateLockStrategy(s pgx.LockStrategy) error {
if s != pgx.LockStrategyAdvisory && s != pgx.LockStrategyTable {
return fmt.Errorf("unsupported lock strategy %q", s)
}
return nil
} Type guard
func isKnownLockStrategy(s pgx.LockStrategy) bool {
return s == pgx.LockStrategyAdvisory || s == pgx.LockStrategyTable
} Try / catch
if err := drv.Lock(); err != nil {
if strings.Contains(err.Error(), "unknown lock strategy") {
return fmt.Errorf("set Config.LockStrategy to pgx.LockStrategyAdvisory or pgx.LockStrategyTable: %w", err)
}
return err
} Prevention
- Always assign LockStrategy using the exported constants, never raw strings
- Validate user-supplied strategy names against the constants at config load time
- Rely on library defaults instead of hand-building Config when possible
When it happens
Trigger: Constructing a pgx Config (or WithInstance/Open path) with LockStrategy set to a value other than pgx.LockStrategyAdvisory or pgx.LockStrategyTable (e.g. an empty string, or a user-supplied string like "advisory" that was never converted to the typed constant) and then calling Lock.
Common situations: Hand-building a Config instead of relying on defaults (zero-value empty string); parsing a user string into LockStrategy without validating against the defined constants; switching from another driver's config struct that names lock strategies differently.
Related errors
- unable to parse option x-migrations-table-quoted: %w
- x-migrations-table must be quoted (for instance '"migrate"."
- unable to parse option x-multi-statement: %w
- no database name
- no schema
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/88c0f5d30cc0bc7b.
Report an issue: GitHub.