golang-migrate/migrate · critical
Register called twice for driver
Error message
Register called twice for driver
What it means
source.Register panics when the given source driver name already exists in the global registry. Because most source drivers register themselves in init(), importing two packages that claim the same source name (or the same package under two module versions) causes the second Register to panic.
Source
Thrown at source/driver.go:104
driversMu.RLock()
d, ok := drivers[u.Scheme]
driversMu.RUnlock()
if !ok {
return nil, fmt.Errorf("source driver: unknown driver '%s' (forgotten import?)", u.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
- Deduplicate imports / consolidate module versions so the driver registers once.
- Use a unique name for your custom source driver.
- Wrap registration in sync.Once when it cannot live in init().
- In tests, register distinct names per test case or construct drivers directly instead of registering.
Example fix
// before
source.Register("s3", d1)
source.Register("s3", d2) // panic
// after
source.Register("s3", d1)
source.Register("s3-custom", d2) Defensive patterns
Strategy: validation
Validate before calling
func registerSourceOnce(name string, d source.Driver) {
for _, n := range source.List() {
if n == name {
return
}
}
source.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("duplicate source driver: %s", s)
return
}
panic(r)
}
}()
source.Register(name, srcDrv) Prevention
- Verify go.mod doesn't pull two versions of the same source driver module (go mod graph).
- Use unique names for every custom source driver.
- Restrict Register calls to init() or a sync.Once-guarded setup.
- Run go mod tidy and review imports when adding source driver packages.
When it happens
Trigger: Importing two source driver packages registering the same name, one module imported at two versions in go.mod, or a custom driver registered twice (e.g. once in tests, once in init).
Common situations: Forked copies of a source driver both imported, duplicate source names in custom drivers, test suites calling Register repeatedly without isolation.
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/84d7fa62bb957014.
Report an issue: GitHub.