{"record":{"id":"d21d58c99cbde53f","repo":"benbjohnson/litestream","slug":"sync-database-s-w","errorCode":null,"errorMessage":"sync database %s: %w","messagePattern":"sync database (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/litestream/replicate.go","lineNumber":403,"sourceCode":"\t\t// Run one-shot replication in a goroutine so the caller can wait on execCh.\n\t\tgo c.runOnce(ctx)\n\t}\n\n\treturn nil\n}\n\n// runOnce performs one-shot replication for all databases.\n// It syncs all databases, optionally takes snapshots, and enforces retention.\nfunc (c *ReplicateCommand) runOnce(ctx context.Context) {\n\tvar err error\n\tdefer func() { c.execCh <- err }()\n\n\tfor _, db := range c.Store.DBs() {\n\t\tslog.Info(\"syncing database\", \"path\", db.Path())\n\n\t\t// Sync the database to process any pending WAL changes.\n\t\tif err = db.Sync(ctx); err != nil {\n\t\t\terr = fmt.Errorf(\"sync database %s: %w\", db.Path(), err)\n\t\t\treturn\n\t\t}\n\n\t\t// Sync the replica to upload any pending LTX files.\n\t\tif err = db.Replica.Sync(ctx); err != nil {\n\t\t\terr = fmt.Errorf(\"sync replica for %s: %w\", db.Path(), err)\n\t\t\treturn\n\t\t}\n\n\t\t// Force a snapshot if requested.\n\t\tif c.forceSnapshot {\n\t\t\tslog.Info(\"taking snapshot\", \"path\", db.Path())\n\t\t\tif _, err = db.Snapshot(ctx); err != nil {\n\t\t\t\terr = fmt.Errorf(\"snapshot %s: %w\", db.Path(), err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/replicate.go#L385-L421","documentation":"In one-shot (`-once`) mode, runOnce syncs each configured database (applying pending WAL changes and uploading LTX files) and returns the first error via named return. A failure from db.Sync — corrupted WAL, locked database, I/O error — is wrapped as \"sync database <path>\" so the failing database is identified.","triggerScenarios":"`db.Sync(ctx)` returns error during a `-once` run: the SQLite file is locked by another process, WAL is corrupted, disk is full, or the DB was modified concurrently in an unsupported way.","commonSituations":"Another process holds an exclusive lock during the one-shot backup; WAL/shm files out of sync after a crash; running litestream as a different user than the app writing the DB.","solutions":["Inspect the wrapped inner error for the SQLite-level cause (lock, corruption, I/O)","Retry the one-shot sync once the writer releases locks / quiesce the application","If local LTX/WAL state is corrupted, run `litestream reset` for that database and re-sync","Ensure litestream runs with read/write access to the DB, WAL, and SHM files"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"# pre-check DB accessibility before one-shot sync\n[ -f \"$DB\" ] && [ -w \"${DB}-wal\" ] || echo \"warn: wal missing/unwritable\"\nlsof \"$DB\" && echo \"warn: database in use by another process\"","typeGuard":null,"tryCatchPattern":"if err := cmd.Run(ctx); err != nil {\n    var dbErr error\n    if strings.Contains(err.Error(), \"sync database\") {\n        dbErr = err // path is embedded in message; unwrap for SQLite cause\n        for e := errors.Unwrap(err); e != nil; e = errors.Unwrap(e) {\n            log.Printf(\"sqlite cause: %v\", e)\n        }\n    }\n    return err\n}","preventionTips":["Schedule one-shot syncs when writers are quiescent or accept brief locks","Ensure litestream has rw access to DB, -wal and -shm files","Avoid running multiple litestream instances against the same database","Use `litestream reset` only when local LTX state is confirmed corrupted","Monitor disk space — full disks break WAL checkpointing and syncs"],"tags":["sync","sqlite","wal","backup"],"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"}