golang-migrate/migrate · error
session is closed
Error message
session is closed
What it means
ErrClosedSession is returned by WithInstance when the provided *gocql.Session has already been closed (session.Closed() is true). The driver needs a live session to query and update the migrations table, so it rejects a closed one instead of failing later with cryptic gocql errors.
Source
Thrown at database/cassandra/cassandra.go:35
func init() {
db := new(Cassandra)
database.Register("cassandra", db)
}
var (
multiStmtDelimiter = []byte(";")
DefaultMultiStatementMaxSize = 10 * 1 << 20 // 10 MB
)
var DefaultMigrationsTable = "schema_migrations"
var (
ErrNilConfig = errors.New("no config")
ErrNoKeyspace = errors.New("no keyspace provided")
ErrDatabaseDirty = errors.New("database is dirty")
ErrClosedSession = errors.New("session is closed")
)
type Config struct {
MigrationsTable string
KeyspaceName string
MultiStatementEnabled bool
MultiStatementMaxSize int
}
type Cassandra struct {
session *gocql.Session
isLocked atomic.Bool
// Open and WithInstance need to guarantee that config is never nil
config *Config
}
func WithInstance(session *gocql.Session, config *Config) (database.Driver, error) {View on GitHub (pinned to 01a9643f14)
Solutions
- Create (or re-create) the gocql session after closing: session, err := cluster.CreateSession() and pass the fresh session to WithInstance.
- Reorder code so session.Close() runs only after migrations are done (move defer Close to after migration completion).
- Check session.Closed() yourself before calling WithInstance and surface a clear message.
Example fix
// before session.Close() driver, err := cassandra.WithInstance(session, cfg) // after driver, err := cassandra.WithInstance(session, cfg) // ... use driver ... session.Close()
Defensive patterns
Strategy: type-guard
Validate before calling
if session.Closed() {
return fmt.Errorf("cannot run migrations: gocql session is already closed")
} Type guard
func sessionAlive(s *gocql.Session) bool { return s != nil && !s.Closed() } Try / catch
driver, err := cassandra.WithInstance(session, cfg)
if errors.Is(err, cassandra.ErrClosedSession) {
return fmt.Errorf("session closed before migrations; create it after connection setup")
} Prevention
- Place session.Close() only after all migration work completes.
- Avoid `defer session.Close()` at the top of a function that also runs migrations.
- Do not share one session across setup and teardown phases in tests.
When it happens
Trigger: Calling cassandra.WithInstance(session, config) after cluster.Session() result was closed via session.Close(), or reusing a session captured before a shutdown/defer Close ran.
Common situations: defer session.Close() at the top of a function followed by driver setup, application shutdown hooks re-running migrations, or tests sharing a session closed in a previous teardown.
Related errors
AI-assisted analysis of golang-migrate/migrate@01a9643f14 (2026-09-02).
Data as JSON: /api/errors/c64fd3e72d882862.
Report an issue: GitHub.