{"record":{"id":"398a0770c4a2b48e","repo":"benbjohnson/litestream","slug":"integrity-check-w","errorCode":null,"errorMessage":"integrity check: %w","messagePattern":"integrity check: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":1355,"sourceCode":"\tdb, err := sql.Open(\"sqlite\", dbPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open database for integrity check: %w\", err)\n\t}\n\tdefer func() { _ = db.Close() }()\n\n\tvar pragma string\n\tswitch mode {\n\tcase IntegrityCheckQuick:\n\t\tpragma = \"quick_check\"\n\tcase IntegrityCheckFull:\n\t\tpragma = \"integrity_check\"\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported integrity check mode: %d\", mode)\n\t}\n\n\tvar result string\n\tif err := db.QueryRowContext(ctx, \"PRAGMA \"+pragma).Scan(&result); err != nil {\n\t\treturn fmt.Errorf(\"integrity check: %w\", err)\n\t}\n\tif result != \"ok\" {\n\t\treturn fmt.Errorf(\"integrity check failed: %s\", result)\n\t}\n\n\t// Clean up -shm and -wal files that SQLite may create during the PRAGMA.\n\t_ = os.Remove(dbPath + \"-shm\")\n\t_ = os.Remove(dbPath + \"-wal\")\n\n\treturn nil\n}\n\n// findBestV3SnapshotForTimestamp returns the best v0.3.x snapshot for the given timestamp.\n// Returns nil if no suitable snapshot exists.\nfunc (r *Replica) findBestV3SnapshotForTimestamp(ctx context.Context, client ReplicaClientV3, timestamp time.Time) (*SnapshotInfoV3, error) {\n\tgenerations, err := client.GenerationsV3(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"list v0.3.x generations: %w\", err)","sourceCodeStart":1337,"sourceCodeEnd":1373,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L1337-L1373","documentation":"checkIntegrity runs 'PRAGMA quick_check' or 'PRAGMA integrity_check' via db.QueryRowContext and this error wraps a failure to execute/scan that query — as opposed to the check returning a bad result. It indicates SQLite could not run the check: database open/IO errors, context cancellation, or driver-level failures.","triggerScenarios":"Restore with IntegrityCheck enabled where QueryRowContext(ctx, \"PRAGMA \"+pragma).Scan(&result) errors: ctx cancelled/timed out mid-PRAGMA, unreadable/corrupt file causing driver errors, or the restored file being locked by another process.","commonSituations":"Very large databases with a short context deadline; another process holding the restored DB open during the check; antivirus/backup software interfering with the file; disk I/O errors.","solutions":["Inspect the wrapped driver error for 'interrupted' (context) vs I/O messages.","Increase the context deadline/timeout for large restores.","Ensure no other process is holding db.sqlite, -wal, or -shm open during restore.","Re-run the restore to rule out a transient I/O error.","If the driver reports disk I/O errors, check hardware/filesystem health."],"exampleFix":"// before\nctx := context.Background()\n// after\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)\ndefer cancel()","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := restore(ctx, opt); err != nil && strings.Contains(err.Error(), \"integrity check:\") {\n    if errors.Is(err, context.DeadlineExceeded) {\n        // retry with a larger timeout\n    }\n}","preventionTips":["Give integrity PRAGMAs a long-lived context on large databases","Ensure the restored file is not locked by other processes or scanners","Exclude restore output paths from antivirus/backup scanning","Check filesystem health if driver I/O errors recur"],"tags":["sqlite","pragma","integrity-check","context"],"backgroundTag":"database-query-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}