{"record":{"id":"8708ef3c03864327","repo":"golang-migrate/migrate","slug":"conn-v-db-v-8708ef","errorCode":null,"errorMessage":"conn: %v, db: %v","messagePattern":"conn: (.+?), db: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"database/pgx/pgx.go","lineNumber":244,"sourceCode":"\t\tStatementTimeout:      time.Duration(statementTimeout) * time.Millisecond,\n\t\tMultiStatementEnabled: multiStatementEnabled,\n\t\tMultiStatementMaxSize: multiStatementMaxSize,\n\t\tLockStrategy:          lockStrategy,\n\t\tLockTable:             lockTable,\n\t})\n\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn px, nil\n}\n\nfunc (p *Postgres) Close() error {\n\tconnErr := p.conn.Close()\n\tdbErr := p.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 (p *Postgres) Lock() error {\n\treturn database.CasRestoreOnErr(&p.isLocked, false, true, database.ErrLocked, func() error {\n\t\tswitch p.config.LockStrategy {\n\t\tcase LockStrategyAdvisory:\n\t\t\treturn p.applyAdvisoryLock()\n\t\tcase LockStrategyTable:\n\t\t\treturn p.applyTableLock()\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unknown lock strategy \\\"%s\\\"\", p.config.LockStrategy)\n\t\t}\n\t})\n}\n\nfunc (p *Postgres) Unlock() error {","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/pgx/pgx.go#L226-L262","documentation":"Postgres.Close closes both the underlying pgx connection pool (p.conn) and the legacy database/sql handle (p.db) and reports any failure from either. Because both errors are reported together with %v, one of them may print <nil>; the error means at least one Close failed. It typically indicates the connection was already closed or is unreachable during teardown.","triggerScenarios":"Calling Close on a Postgres driver instance after the underlying connection or sql.DB was already closed (double Close), or when the network/database has gone away so conn.Close or db.Close returns an error such as 'conn closed' or a context/network failure.","commonSituations":"Deferring Close twice (e.g. both in Open error-handling paths and in main); closing a shared driver instance from multiple places; infrastructure tearing down the DB connection before the app exits; nil-ish errors surfaced from a previously failed connection.","solutions":["Ensure Close is called exactly once per driver instance; guard with sync.Once or check that Open succeeded before closing.","Read the wrapped message: 'conn: <nil>, db: ...' tells you which handle failed and why; fix the root cause it reports.","If the error is 'sql: database is closed' / 'conn closed', remove the redundant close call rather than retrying.","Ignore Close errors on process exit only deliberately (log them), since they rarely affect data integrity."],"exampleFix":"// before\nm, _ := source.Open(...)\nd, _ := pgx.Open(dsn)\ninst, _ := migrate.NewWithInstance(...)\ninst.Close() // first close\ndefer inst.Close() // second close -> conn/db already closed\n// after\ninst, err := migrate.NewWithInstance(...)\nif err != nil { ... }\ndefer inst.Close() // single close","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"var closeOnce sync.Once\ncloseDriver := func() {\n    closeOnce.Do(func() {\n        if err := drv.Close(); err != nil {\n            log.Printf(\"driver close: %v (inspect conn:/db: parts)\", err)\n        }\n    })\n}\ndefer closeDriver()","preventionTips":["Close each driver instance exactly once (sync.Once or explicit ownership)","Do not defer Close on both the migrate instance and the raw driver for the same handle","Log Close errors but treat 'already closed' as benign at shutdown"],"tags":["postgresql","connection-close","resource-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"}