{"record":{"id":"691404bd4ae05041","repo":"benbjohnson/litestream","slug":"restore-from-backup-w","errorCode":null,"errorMessage":"restore from backup: %w","messagePattern":"restore from backup: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"db.go","lineNumber":762,"sourceCode":"\t\treturn fmt.Errorf(\"stat database: %w\", err)\n\t}\n\n\tif dir := filepath.Dir(db.Path()); dir != \".\" {\n\t\tif err := os.MkdirAll(dir, 0o750); err != nil {\n\t\t\treturn fmt.Errorf(\"create parent directory: %w\", err)\n\t\t}\n\t}\n\n\topt := NewRestoreOptions()\n\topt.OutputPath = db.Path()\n\topt.IntegrityCheck = IntegrityCheckQuick\n\n\tif err := db.Replica.Restore(ctx, opt); err != nil {\n\t\tif errors.Is(err, ErrTxNotAvailable) || errors.Is(err, ErrNoSnapshots) {\n\t\t\tdb.Logger.Debug(\"no backup found, will create fresh database\")\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"restore from backup: %w\", err)\n\t}\n\n\tdb.Logger.Info(\"database restored from backup\", \"path\", db.Path())\n\treturn nil\n}\n\n// Open initializes the background monitoring goroutine.\nfunc (db *DB) Open() (err error) {\n\tdb.mu.Lock()\n\tif db.opened {\n\t\tdb.mu.Unlock()\n\t\treturn nil // already open\n\t}\n\t// Recreate context for fresh start (handles reopen after close)\n\tdb.ctx, db.cancel = context.WithCancel(context.Background())\n\tdb.mu.Unlock()\n\n\t// Validate fields on database.","sourceCodeStart":744,"sourceCodeEnd":780,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/db.go#L744-L780","documentation":"DB.EnsureExists(ctx) attempts to restore the database from the replica via db.Replica.Restore(ctx, opt). If the restore fails with anything other than ErrTxNotAvailable or ErrNoSnapshots (which mean \"no backup yet\" and are treated as fresh-start), litestream wraps the error as \"restore from backup\". The database is NOT usable until this is resolved.","triggerScenarios":"Replica.Restore failing during the local restore: remote LTX fetch failures (network/credentials), integrity check failure (opt.IntegrityCheck = IntegrityCheckQuick), corrupted remote LTX files, or unsupported/failed output write to db.Path().","commonSituations":"Remote replica truncated or corrupted by lifecycle rules; network interruption mid-restore; restore target path unwritable; quick integrity check failing because the latest LTX chain is inconsistent; provider credentials valid for listing but not for GetObject.","solutions":["Unwrap the error to see whether the failure was remote fetch, write, or integrity check.","Inspect the replica contents with `litestream ltx -level all` to verify the LTX chain and snapshots are intact.","Verify read (GetObject) permissions and network access to the replica destination, then retry the restore.","If remote state is corrupted/unusable and you accept data loss, remove/renaming the replica path and start fresh (a new DB will be created on Open()) — otherwise repair from another replica copy."],"exampleFix":"// before\nif err := db.EnsureExists(ctx); err != nil {\n    log.Fatal(err) // opaque \"restore from backup: ...\"\n}\n// after\nif err := db.EnsureExists(ctx); err != nil {\n    if errors.Is(err, litestream.ErrTxNotAvailable) {\n        // no backup yet: fresh DB will be created\n    } else {\n        log.Fatalf(\"restore failed: %v\", err) // inspect wrapped cause\n    }\n}","handlingStrategy":"try-catch","validationCode":"// preflight: read access to the replica before attempting restore\n// e.g. run `litestream ltx -level all` against the replica and fail fast if unreadable","typeGuard":null,"tryCatchPattern":"if err := db.EnsureExists(ctx); err != nil {\n    switch {\n    case errors.Is(err, litestream.ErrTxNotAvailable), errors.Is(err, litestream.ErrNoSnapshots):\n        // treat as fresh start\n    default:\n        return fmt.Errorf(\"restore from backup failed: %w\", err)\n    }\n}","preventionTips":["Do not let cloud lifecycle policies delete LTX files still needed for restore.","Grant GetObject (read) in addition to list permissions on the replica prefix.","Periodically run test restores (litestream restore to a scratch dir) to validate the backup.","Ensure the restore output path is writable and integrity check settings match your data size."],"tags":["restore","replica","storage","integrity"],"backgroundTag":"http-error-response","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}