golang-migrate/migrate · warning
conn: %v, db: %v
Error message
conn: %v, db: %v
What it means
Close() on the Redshift driver closes both the raw connection and the database handle, then reports any failures combined as 'conn: %v, db: %v' (with <nil> for the healthy side). Redshift does not support postgres advisory locks, so cleanup correctness relies solely on these close calls; a failure here means connections may linger until the server times them out.
Source
Thrown at database/redshift/redshift.go:122
migrationsTable := purl.Query().Get("x-migrations-table")
px, err := WithInstance(db, &Config{
DatabaseName: purl.Path,
MigrationsTable: migrationsTable,
})
if err != nil {
return nil, err
}
return px, nil
}
func (p *Redshift) Close() error {
connErr := p.conn.Close()
dbErr := p.db.Close()
if connErr != nil || dbErr != nil {
return fmt.Errorf("conn: %v, db: %v", connErr, dbErr)
}
return nil
}
// Redshift does not support advisory lock functions: https://docs.aws.amazon.com/redshift/latest/dg/c_unsupported-postgresql-functions.html
func (p *Redshift) Lock() error {
if !p.isLocked.CompareAndSwap(false, true) {
return database.ErrLocked
}
return nil
}
func (p *Redshift) Unlock() error {
if !p.isLocked.CompareAndSwap(true, false) {
return database.ErrNotLocked
}
return nil
}View on GitHub (pinned to 01a9643f14)
Solutions
- Read both parts of the combined message; ignore 'sql: database is closed' if your code intentionally closed the *sql.DB first
- Ensure only one owner closes shared handles (pass the *sql.DB to the driver and let Close() own cleanup)
- Check VPC/security-group connectivity and Redshift's connection limits if closes consistently fail
Example fix
// before
db, _ := sql.Open(...)
d, _ := redshift.WithInstance(instance, cfg)
defer db.Close() // closes handle the driver also closes
// after
d, _ := redshift.WithInstance(instance, cfg)
defer func() {
if err := d.Close(); err != nil {
log.Printf("migrator close: %v", err)
}
}() // single close owner Defensive patterns
Strategy: try-catch
Validate before calling
if redshiftConn.conn == nil || redshiftConn.db == nil {
return errors.New("redshift migrator already closed or not initialized")
} Try / catch
if err := driver.Close(); err != nil {
if strings.Contains(err.Error(), "sql: database is closed") {
return nil // intentional prior close
}
return fmt.Errorf("closing redshift migrator: %w", err)
} Prevention
- Let the migrator own the *sql.DB; do not close the same handle twice
- Use sync.Once around Close in long-lived workers
- Monitor Redshift connection limits/timeouts that reap idle connections
When it happens
Trigger: Calling Driver.Close() after the Redshift connection was already terminated (idle timeout, admin intervention, network interruption) or when the *sql.DB was closed by the caller first.
Common situations: Long-running migration workers whose connections are reaped by Redshift's connection limits; Lambda/short-lived jobs where the caller's deferred close of *sql.DB runs before the driver's Close; network blips to the Redshift endpoint.
Related errors
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/b4218ce4f55eb07e.
Report an issue: GitHub.