golang-migrate/migrate · critical
Register driver is nil
Error message
Register driver is nil
What it means
database.Register panics (not an error return) when the driver argument is nil. The global driver registry stores database.Driver implementations by name, and a nil entry would cause nil-pointer panics later during Open, so it is rejected eagerly at registration time.
Source
Thrown at database/driver.go:106
return nil, err
}
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
- Ensure the Driver value is fully constructed before calling Register; construct it after all dependencies are ready.
- Guard against import-cycle-induced nil package vars by moving registration to an explicit init function called from main.
- Check the driver constructor for swallowed errors that leave a nil interface value.
Example fix
// before
func init() { database.Register("mydb", drv) } // drv is nil on failure path
// after
func init() {
d, err := newDriver()
if err != nil { panic(err) }
database.Register("mydb", d)
} Defensive patterns
Strategy: validation
Validate before calling
if driver == nil {
panic("refusing to call database.Register with nil driver")
}
database.Register(name, driver) Type guard
func isNilDriver(d database.Driver) bool {
if d == nil { return true }
return reflect.ValueOf(d).Kind() == reflect.Ptr && reflect.ValueOf(d).IsNil()
} Try / catch
// Register panics rather than returning error; isolate at startup:
func mustRegister(name string, d database.Driver) {
defer func() {
if r := recover(); r != nil {
log.Fatalf("driver registration failed: %v", r)
}
}()
database.Register(name, d)
} Prevention
- Always construct drivers via constructors that return (Driver, error) and check the error.
- Register drivers in a single explicit setup function instead of scattered init()s.
- Write a smoke test that calls database.List() after setup and asserts your driver is present.
When it happens
Trigger: Calling database.Register("mydb", nil) directly, or registering a variable/interface that is nil due to failed initialization of a custom driver, often from a package's init().
Common situations: Custom database drivers registered in init() where construction failed silently; copied registration boilerplate with the driver left unset; import cycles causing partially initialized package variables.
Related errors
- Register driver is nil
- Register called twice for driver
- Register called twice for driver
- 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/7e15c220fcf9e0c9.
Report an issue: GitHub.