{"record":{"id":"785af5d13f88366d","repo":"benbjohnson/litestream","slug":"cannot-restore-sqlite-sidecar-path-already-exists","errorCode":null,"errorMessage":"cannot restore, SQLite sidecar path already exists: %s. Use -force to overwrite","messagePattern":"cannot restore, SQLite sidecar path already exists: (.+?)\\. Use -force to overwrite","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/restore.go","lineNumber":285,"sourceCode":"\nfunc (c *RestoreCommand) prepareOutputPath(path string, force bool) error {\n\tinfo, err := os.Stat(path)\n\tif os.IsNotExist(err) {\n\t\treturn nil\n\t} else if err != nil {\n\t\treturn fmt.Errorf(\"cannot access output path: %w\", err)\n\t}\n\tif info.IsDir() {\n\t\treturn fmt.Errorf(\"cannot restore, output path is a directory: %s\", path)\n\t}\n\n\tif info.Size() > 0 && !force {\n\t\treturn fmt.Errorf(\"cannot restore, output path already exists and is not empty: %s. Use -force to overwrite\", path)\n\t}\n\n\tfor _, sidecarPath := range []string{path + \"-wal\", path + \"-shm\", path + \"-journal\"} {\n\t\tif _, err := os.Stat(sidecarPath); err == nil && !force {\n\t\t\treturn fmt.Errorf(\"cannot restore, SQLite sidecar path already exists: %s. Use -force to overwrite\", sidecarPath)\n\t\t} else if err != nil && !os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"cannot access SQLite sidecar path: %w\", err)\n\t\t}\n\t}\n\n\tfor _, removePath := range []string{path, path + \"-wal\", path + \"-shm\", path + \"-journal\"} {\n\t\tif err := os.Remove(removePath); err != nil && !os.IsNotExist(err) {\n\t\t\treturn fmt.Errorf(\"remove existing output path: %w\", err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// loadFromURL creates a replica & updates the restore options from a replica URL.\nfunc (c *RestoreCommand) loadFromURL(ctx context.Context, replicaURL string, ifDBNotExists bool, opt *litestream.RestoreOptions) (*litestream.Replica, error) {\n\tif opt.OutputPath == \"\" {\n\t\treturn nil, &usageError{\n\t\t\tmessage: \"-o is required when restoring from a replica URL\",","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/restore.go#L267-L303","documentation":"prepareOutputPath also checks SQLite sidecar files (<output>-wal, <output>-shm, <output>-journal). If any of these exists and -force was not passed, restore aborts, because leaving a stale WAL/SHM/journal next to a freshly restored database can corrupt it or resurrect old data. The error names the specific sidecar path that collided.","triggerScenarios":"Restoring to a path where a previous database (or running SQLite connection) left -wal/-shm/-journal files behind, without -force. The check `os.Stat(sidecarPath); err == nil && !force` fires.","commonSituations":"Restoring over the location of a database that was recently in use (SQLite left the -wal/-shm behind after an unclean shutdown); retrying a restore into the same path after deleting only the .db file; a running app still holding the database at that path.","solutions":["Re-run the restore with -force, which removes the stale sidecar files before restoring","Manually delete the reported sidecar file (and the db if desired), then re-run","Ensure no application is running against that database path, then restore"],"exampleFix":"// before\nrm /data/app.db\nlitestream restore -o /data/app.db /path/to/db\ncannot restore, SQLite sidecar path already exists: /data/app.db-wal. Use -force to overwrite\n// after\nlitestream restore -force -o /data/app.db /path/to/db","handlingStrategy":"validation","validationCode":"for _, ext := range []string{\"-wal\", \"-shm\", \"-journal\"} {\n    if _, err := os.Stat(outputPath + ext); err == nil && !forceFlag {\n        return fmt.Errorf(\"stale sidecar %s exists; pass -force\", outputPath + ext)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := cmd.Run(ctx); err != nil {\n    if strings.Contains(err.Error(), \"SQLite sidecar path already exists\") {\n        // stop the app using that path, then re-run with -force\n    }\n    return err\n}","preventionTips":["Stop any application using the database at the output path before restoring","When cleaning a previous restore, remove the -wal, -shm and -journal files too, not just the .db","Use -force for restore-into-same-path workflows so stale sidecars are removed safely","Check for lingering sidecars with `ls /path/to/db*` before restoring"],"tags":["sqlite","sidecar-files","restore"],"backgroundTag":"file-already-exists","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"}