{"record":{"id":"e7de2ba3d0162fcd","repo":"golang-migrate/migrate","slug":"conn-v-db-v","errorCode":null,"errorMessage":"conn: %v, db: %v","messagePattern":"conn: (.+?), db: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"database/firebird/firebird.go","lineNumber":104,"sourceCode":"\t}\n\n\tpx, err := WithInstance(db, &Config{\n\t\tMigrationsTable: purl.Query().Get(\"x-migrations-table\"),\n\t\tDatabaseName:    purl.Path,\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn px, nil\n}\n\nfunc (f *Firebird) Close() error {\n\tconnErr := f.conn.Close()\n\tdbErr := f.db.Close()\n\tif connErr != nil || dbErr != nil {\n\t\treturn fmt.Errorf(\"conn: %v, db: %v\", connErr, dbErr)\n\t}\n\treturn nil\n}\n\nfunc (f *Firebird) Lock() error {\n\tif !f.isLocked.CompareAndSwap(false, true) {\n\t\treturn database.ErrLocked\n\t}\n\treturn nil\n}\n\nfunc (f *Firebird) Unlock() error {\n\tif !f.isLocked.CompareAndSwap(true, false) {\n\t\treturn database.ErrNotLocked\n\t}\n\treturn nil\n}\n","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/firebird/firebird.go#L86-L122","documentation":"In Firebird.Close, both the raw connection and sql.DB are closed; if either returns an error, the driver wraps both with fmt.Errorf(\"conn: %v, db: %v\", ...). It reports that cleanup of the Firebird connection pool failed, possibly on both handles simultaneously. Note the wrapping discards error identity, so you must string-match to classify it.","triggerScenarios":"Calling migrate.Close() (which calls Firebird.Close) when the underlying sql.DB was already closed, the TCP connection to Firebird dropped, or the conn handle was closed elsewhere concurrently.","commonSituations":"Double-closing a migrate instance, network interruption before shutdown, closing the *sql.DB yourself before migrate.Close(), app shutdown with a stale Firebird connection.","solutions":["Close the migrate instance once and let it own the connection lifecycle","Check network/DB availability and retry Close","Treat Close errors as non-fatal cleanup warnings if migration already succeeded","If you own the *sql.DB, close it only after migrate.Close() returns"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if sqlDB == nil || conn == nil {\n    return fmt.Errorf(\"firebird handles already closed; skip migrate.Close\")\n}","typeGuard":null,"tryCatchPattern":"if err := m.Close(); err != nil {\n    // wrapped as \"conn: %v, db: %v\" — log and continue on shutdown\n    log.Printf(\"firebird close (non-fatal): %v\", err)\n}","preventionTips":["Let migrate own the connection; do not close the *sql.DB separately","Call Close exactly once per migrate instance (use sync.Once in wrappers)","Treat Close errors during shutdown as warnings unless migrations are in flight"],"tags":["go","golang-migrate","firebird","connection-close","cleanup"],"backgroundTag":"connection-close-failed","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}