ory/hydra · error
driver %T does not support online restore
Error message
driver %T does not support online restore
What it means
Inside conn.Raw, the code type-asserts the unwrapped driver connection to an interface with NewRestore(srcUri string) (*moderncsqlite.Backup, error). If the concrete driver does not implement online backup, errors.Errorf produces 'driver %T does not support online restore', reporting the actual driver type.
Source
Thrown at oryx/popx/migrator.go:103
// pop wraps the modernc.org/sqlite driver with otelsql for tracing; we
// unwrap via the otelsql Raw() accessor before reaching the driver-specific
// NewRestore method on the underlying *sqlite.conn.
func restoreSQLiteOnline(ctx context.Context, db *sql.DB, srcPath string) error {
conn, err := db.Conn(ctx)
if err != nil {
return errors.Wrap(err, "failed to acquire sql.Conn for restore")
}
defer func() { _ = conn.Close() }()
return conn.Raw(func(driverConn any) error {
if w, ok := driverConn.(interface{ Raw() driver.Conn }); ok {
driverConn = w.Raw()
}
restorer, ok := driverConn.(interface {
NewRestore(srcUri string) (*moderncsqlite.Backup, error)
})
if !ok {
return errors.Errorf("driver %T does not support online restore", driverConn)
}
// See: https://sqlite.org/backup.html .
backup, err := restorer.NewRestore(srcPath)
if err != nil {
return errors.Wrap(err, "NewRestore failed")
}
// Step(-1) copies all remaining pages in one call.
for {
more, stepErr := backup.Step(-1)
if stepErr != nil {
_ = backup.Finish()
return errors.Wrap(stepErr, "backup.Step failed")
}
if !more {
break
}
}
return errors.Wrap(backup.Finish(), "backup.Finish failed")View on GitHub (pinned to 4174065ffb)
Solutions
- Use the supported modernc.org/sqlite driver (via the otelsql wrapper the library configures) for online restore
- Remove or adjust extra driver wrappers so the Raw() unwrap reaches a *sqlite.conn
- Fall back to file-copy restore instead of the online backup API
- Guard the restore with a capability check before invoking it
Example fix
// before import _ "github.com/mattn/go-sqlite3" // after import _ "modernc.org/sqlite"
Defensive patterns
Strategy: fallback
Type guard
func supportsOnlineRestore(driverConn any) bool {
if w, ok := driverConn.(interface{ Raw() driver.Conn }); ok {
driverConn = w.Raw()
}
_, ok := driverConn.(interface {
NewRestore(srcUri string) (*moderncsqlite.Backup, error)
})
return ok
} Try / catch
if err := restoreSQLiteOnline(ctx, db, srcPath); err != nil {
if strings.Contains(err.Error(), "does not support online restore") {
// fall back to file-based restore
err = fileCopyRestore(db, srcPath)
}
return err
} Prevention
- Standardize on modernc.org/sqlite (as wrapped by the library) for SQLite connections
- Avoid stacking custom driver wrappers that break Raw() unwrapping
- Document the driver requirement for online backup features
- Add a capability check at startup and select a restore strategy accordingly
When it happens
Trigger: Running the SQLite online-restore path while connected via a driver whose connection is neither *sqlite.conn nor otherwise implementing NewRestore — e.g. a pure-Go alternative driver, a wrapped driver not unwrappable via Raw(), or mattn/go-sqlite3.
Common situations: Swapping the SQLite driver (cgo vs modernc), stacking extra driver wrappers that break the Raw() unwrapping chain, running migrations on a non-SQLite database that mistakenly routes into this code path.
Related errors
- NewRestore failed
- backup.Step failed
- backup.Finish failed
- failed to acquire sql.Conn for restore
- The DSN connection string looks like a SQLite connection, bu
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/3c4c2a4e3ff1b176.
Report an issue: GitHub.