golang-migrate/migrate · critical
Register called twice for driver
Error message
Register called twice for driver
What it means
database.Register panics if a driver with the same name was already registered in the global registry. This prevents silent driver shadowing; drivers are typically registered in package init(), so importing two packages that both register the same name triggers this.
Source
Thrown at database/driver.go:109
driversMu.RLock()
d, ok := drivers[scheme]
driversMu.RUnlock()
if !ok {
return nil, fmt.Errorf("database driver: unknown driver %v (forgotten import?)", scheme)
}
return d.Open(url)
}
// Register globally registers a driver.
func Register(name string, driver Driver) {
driversMu.Lock()
defer driversMu.Unlock()
if driver == nil {
panic("Register driver is nil")
}
if _, dup := drivers[name]; dup {
panic("Register called twice for driver " + name)
}
drivers[name] = driver
}
// List lists the registered drivers
func List() []string {
driversMu.RLock()
defer driversMu.RUnlock()
names := make([]string, 0, len(drivers))
for n := range drivers {
names = append(names, n)
}
return names
}
View on GitHub (pinned to 01a9643f14)
Solutions
- Remove or deduplicate the imports causing double registration (check go.mod for two versions of the same driver module).
- Give your custom driver a unique registration name.
- Ensure registration code runs exactly once (guard with sync.Once if not in init()).
- If you must replace a driver, call database.Open with an explicit driver instance rather than re-registering.
Example fix
// before import _ "github.com/x/mypostgres" // registers "postgres" import _ "github.com/y/mypostgres" // also registers "postgres" -> panic // after import _ "github.com/x/mypostgres" // keep only one postgres driver import
Defensive patterns
Strategy: validation
Validate before calling
// guard custom registration against duplicates
func registerOnce(name string, d database.Driver) {
for _, existing := range database.List() {
if existing == name {
return // already registered
}
}
database.Register(name, d)
} Try / catch
defer func() {
if r := recover(); r != nil {
if s, ok := r.(string); ok && strings.HasPrefix(s, "Register called twice for driver") {
log.Warnf("ignoring duplicate driver registration: %s", s)
return
}
panic(r)
}
}()
database.Register(name, driver) Prevention
- Keep exactly one import of each database driver package in go.mod (no duplicate versions).
- Give custom drivers unique, prefixed names (e.g. "myapp-postgres").
- Never register drivers outside init()/one-time setup; use sync.Once for idempotency.
- Before adding a driver import, grep the codebase for existing Register calls with that name.
When it happens
Trigger: Importing two driver packages that both call database.Register("postgres", ...), importing a driver package twice under different module versions, or registering the same custom driver name more than once (e.g. in tests).
Common situations: Duplicate driver names across vendored forks, TestRegisterTwice-style tests confirming the panic, a plugin registering on each reconnection instead of once, or two custom drivers accidentally given the same name.
Related errors
- Register called twice for driver
- Register driver is nil
- Register driver is nil
- not implemented
- failed to init driver with relative path %q: %w
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/eb7a058981cf8ef2.
Report an issue: GitHub.