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

  1. Remove or deduplicate the imports causing double registration (check go.mod for two versions of the same driver module).
  2. Give your custom driver a unique registration name.
  3. Ensure registration code runs exactly once (guard with sync.Once if not in init()).
  4. 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

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


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