golang-migrate/migrate · warning
conn: %v, db: %v
Error message
conn: %v, db: %v
What it means
Wraps both errors from closing the SQLServer driver's two underlying connections: ss.conn (the raw database connection) and ss.db (the *sql.DB handle). It fires from Close when either Close call fails, so both underlying failures are reported in one message. Investigate the individual conn/db errors for the root cause, such as connection already closed or network failure.
Source
Thrown at database/sqlserver/sqlserver.go:187
px, err := WithInstance(db, &Config{
DatabaseName: purl.Path,
MigrationsTable: migrationsTable,
})
if err != nil {
return nil, err
}
return px, nil
}
// Close the database connection
func (ss *SQLServer) Close() error {
connErr := ss.conn.Close()
dbErr := ss.db.Close()
if connErr != nil || dbErr != nil {
return fmt.Errorf("conn: %v, db: %v", connErr, dbErr)
}
return nil
}
// Lock creates an advisory local on the database to prevent multiple migrations from running at the same time.
func (ss *SQLServer) Lock() error {
return database.CasRestoreOnErr(&ss.isLocked, false, true, database.ErrLocked, func() error {
aid, err := database.GenerateAdvisoryLockId(ss.config.DatabaseName, ss.config.SchemaName)
if err != nil {
return err
}
// This will block until the lock is acquired.
// MS Docs: sp_getapplock: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-2017
query := `
DECLARE @lockResult int;
EXEC @lockResult = sp_getapplock @Resource = @p1, @LockMode = 'Exclusive', @LockOwner = 'Session', @LockTimeout = -1;
SELECT @lockResult;`View on GitHub (pinned to 01a9643f14)
Solutions
- Inspect the wrapped conn/db messages to see which close failed; usually the connection was already dead and the error is safe to log and ignore
- Ensure Close is called exactly once and after migrations finish, not twice on the same instance
- Verify network/DB availability before shutdown-time close; re-run migrations only after reconnecting
Example fix
// before
if err := driver.Close(); err != nil { panic(err) }
// after
if err := driver.Close(); err != nil {
log.Printf("migration driver close failed (may be benign on dead conn): %v", err)
} Defensive patterns
Strategy: try-catch
Try / catch
if err := driver.Close(); err != nil {
var conns []string
if errors.As(err, &wrapped) { /* inspect 'conn:' / 'db:' parts */ }
log.Printf("sqlserver driver close: %v", err)
} Prevention
- Close the driver exactly once per instance
- Avoid Close on connections known to be dead after a migration failure — log instead of aborting shutdown
- Check DB/network availability when close errors appear during shutdown
When it happens
Trigger: Calling migrate instance Close while the connection is already broken/closed, or the pool close fails due to network issues or driver state errors.
Common situations: Deferred Close after a migration failure on a dead connection; shutting down an app while the DB server is unavailable; double-closing via both the driver and sql.DB lifecycle management.
Related errors
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/8521e9150baa95df.
Report an issue: GitHub.