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

  1. Ensure the Driver value is fully constructed before calling Register; construct it after all dependencies are ready.
  2. Guard against import-cycle-induced nil package vars by moving registration to an explicit init function called from main.
  3. 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

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


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