{"record":{"id":"ebb5f959588f88cf","repo":"ory/hydra","slug":"failed-to-acquire-sql-conn-for-restore","errorCode":null,"errorMessage":"failed to acquire sql.Conn for restore","messagePattern":"failed to acquire sql\\.Conn for restore","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/popx/migrator.go","lineNumber":91,"sourceCode":"\tdir := mb.sqliteTemplateCacheDir\n\tif dir == \"\" {\n\t\tdir = os.TempDir()\n\t}\n\treturn filepath.Join(dir, \"ory-popx-sqlite-template-\"+hex.EncodeToString(h.Sum(nil))+\".sqlite\")\n}\n\n// restoreSQLiteOnline streams the contents of srcPath into the database\n// represented by db using SQLite's online backup API. The destination\n// connection stays open throughout, so the *sql.DB and any pop.Connection\n// holding it remain valid.\n//\n// pop wraps the modernc.org/sqlite driver with otelsql for tracing; we\n// unwrap via the otelsql Raw() accessor before reaching the driver-specific\n// NewRestore method on the underlying *sqlite.conn.\nfunc restoreSQLiteOnline(ctx context.Context, db *sql.DB, srcPath string) error {\n\tconn, err := db.Conn(ctx)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to acquire sql.Conn for restore\")\n\t}\n\tdefer func() { _ = conn.Close() }()\n\n\treturn conn.Raw(func(driverConn any) error {\n\t\tif w, ok := driverConn.(interface{ Raw() driver.Conn }); ok {\n\t\t\tdriverConn = w.Raw()\n\t\t}\n\t\trestorer, ok := driverConn.(interface {\n\t\t\tNewRestore(srcUri string) (*moderncsqlite.Backup, error)\n\t\t})\n\t\tif !ok {\n\t\t\treturn errors.Errorf(\"driver %T does not support online restore\", driverConn)\n\t\t}\n\t\t// See: https://sqlite.org/backup.html .\n\t\tbackup, err := restorer.NewRestore(srcPath)\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"NewRestore failed\")\n\t\t}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/popx/migrator.go#L73-L109","documentation":"restoreSQLiteOnline performs an online SQLite backup by first acquiring a dedicated *sql.Conn from the pool. If db.Conn(ctx) fails (context canceled/expired or pool acquisition failure), the error is wrapped as 'failed to acquire sql.Conn for restore'.","triggerScenarios":"Calling UpTo on a SQLite database whose connection pool cannot hand out a connection: context deadline exceeded, context canceled, or all pooled connections busy / pool closed.","commonSituations":"Parent request context timing out during a long restore; database already closed; connection pool exhausted by concurrent operations; restore path invoked during app shutdown.","solutions":["Check the wrapped cause: if context deadline, increase the timeout or use context.Background() for migrations","Ensure the *sql.DB is open and not closed before UpTo runs","Avoid holding all pool connections concurrently with the restore","Retry the migration after freeing connections"],"exampleFix":"// before\nerr := mb.UpTo(ctx, -1) // ctx already near deadline\n// after\nrestoreCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\nerr := mb.UpTo(restoreCtx, -1)","handlingStrategy":"try-catch","validationCode":"// Ensure context is healthy and DB is open before migrating\nif err := ctx.Err(); err != nil { return err }\nif err := db.PingContext(ctx); err != nil { return err }","typeGuard":null,"tryCatchPattern":"if err := mb.UpTo(ctx, -1); err != nil {\n  if errors.Is(err, context.DeadlineExceeded) {\n    // retry with a fresh, longer-lived context\n  }\n  if strings.Contains(err.Error(), \"failed to acquire sql.Conn\") {\n    // reduce concurrent pool usage, retry\n  }\n  return err\n}","preventionTips":["Use a dedicated context (not request-scoped) for migrations","Avoid saturating the connection pool while migrations run","Ping the DB and check ctx.Err() before starting migrations","Don't close the *sql.DB before UpTo completes"],"tags":["sqlite","go","database","context"],"backgroundTag":"connection-acquisition-failed","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}