{"record":{"id":"5dcd4b1fb035eba6","repo":"ory/hydra","slug":"backup-step-failed","errorCode":null,"errorMessage":"backup.Step failed","messagePattern":"backup\\.Step failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/popx/migrator.go","lineNumber":115,"sourceCode":"\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}\n\t\t// Step(-1) copies all remaining pages in one call.\n\t\tfor {\n\t\t\tmore, stepErr := backup.Step(-1)\n\t\t\tif stepErr != nil {\n\t\t\t\t_ = backup.Finish()\n\t\t\t\treturn errors.Wrap(stepErr, \"backup.Step failed\")\n\t\t\t}\n\t\t\tif !more {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\treturn errors.Wrap(backup.Finish(), \"backup.Finish failed\")\n\t})\n}\n\n// UpTo runs up to step \"up\" migrations and applies them to the database.\n// If step <= 0 all pending migrations are run.\nfunc (mb *MigrationBox) UpTo(ctx context.Context, step int) (applied int, err error) {\n\tctx, span := startSpan(ctx, MigrationUpOpName, trace.WithAttributes(attribute.Int(\"step\", step)))\n\tdefer otelx.End(span, &err)\n\n\tc := mb.c.WithContext(ctx)\n\n\tnewDbFileName, isOnDiskSQLite := sqliteFilePath(mb.c.URL())","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/popx/migrator.go#L97-L133","documentation":"Returned during SQLite online restore when backup.Step(-1), which copies all remaining pages from the source database, fails. The underlying error comes from the SQLite backup API — source database locked, I/O error, or corrupt source — and Finish is called before returning.","triggerScenarios":"The SQLite backup process fails mid-copy — e.g. the source or destination database is modified/locked during the backup, IO errors occur, or the source file changes underneath the backup handle.","commonSituations":"Concurrent writes to the source DB during restore; disk full while copying pages; source file truncated or corrupted mid-read; another process holding an exclusive lock.","solutions":["Ensure no concurrent writers touch the source or destination during the backup","Check disk space on the destination volume","Inspect the wrapped stepErr for the specific SQLite result code","Retry the restore once the database is quiescent"],"exampleFix":"// before\nbackup running while app writes to DB\n// after\nmu.Lock()\nerr := restoreSQLiteOnline(ctx, db, srcPath)\nmu.Unlock()","handlingStrategy":"retry","validationCode":"// Ensure destination is idle before restore\nif err := db.PingContext(ctx); err != nil { return err }\n// Ensure sufficient disk space\nif free, _ := diskFree(\".\"); free < minRequiredBytes { return errors.New(\"insufficient disk space\") }","typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 3; attempt++ {\n  err := restoreSQLiteOnline(ctx, db, srcPath)\n  if err == nil || !strings.Contains(err.Error(), \"backup.Step failed\") {\n    return err\n  }\n  time.Sleep(time.Duration(attempt+1) * time.Second)\n}\nreturn errors.New(\"restore failed after retries\")","preventionTips":["Stop application writes during the backup/restore window","Monitor disk space where the destination DB lives","Avoid concurrent connections to the destination during restore","Schedule restores during maintenance windows"],"tags":["sqlite","go","backup","io"],"backgroundTag":"sqlite-backup-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"}