Skip to content

Windows Start Fresh Fix#34

Merged
xnodeoncode merged 3 commits intomainfrom
development
Feb 28, 2026
Merged

Windows Start Fresh Fix#34
xnodeoncode merged 3 commits intomainfrom
development

Conversation

@xnodeoncode
Copy link
Owner

Fixed issue with starting with fresh database.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the database “start fresh” flow to better handle Windows-specific SQLite file locking when archiving an encrypted database and restarting with a new one.

Changes:

  • Clears SQLite connection pools and forces Windows GC/finalizers prior to moving the DB file.
  • Adds a Windows-only retry for File.Move after a short delay when an IOException occurs.
  • Attempts to clean up WAL sidecar files (-wal, -shm) to avoid stale journal interference on restart.

catch (Exception ex)
{
// Non-fatal: a stale WAL without its main database is harmless.
_logger.LogWarning("Could not remove WAL companion file {Sidecar}: {Message}", sidecar, ex.Message);
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The WAL sidecar deletion failure path only logs ex.Message and drops the exception/stack trace. Logging the exception object (e.g., _logger.LogWarning(ex, ...)) will preserve the full context for troubleshooting.

Suggested change
_logger.LogWarning("Could not remove WAL companion file {Sidecar}: {Message}", sidecar, ex.Message);
_logger.LogWarning(ex, "Could not remove WAL companion file {Sidecar}", sidecar);

Copilot uses AI. Check for mistakes.
Comment on lines +120 to +135
// Remove WAL companion files if present. These are created when WAL mode is active
// and must be cleaned up so the fresh database starts without a stale journal.
// On Windows these files may also be locked; delete rather than move since the
// archived backup doesn't need them.
foreach (var sidecar in new[] { databasePath + "-wal", databasePath + "-shm" })
{
if (!File.Exists(sidecar)) continue;
try
{
File.Delete(sidecar);
_logger.LogInformation("Removed WAL companion file: {Sidecar}", sidecar);
}
catch (Exception ex)
{
// Non-fatal: a stale WAL without its main database is harmless.
_logger.LogWarning("Could not remove WAL companion file {Sidecar}: {Message}", sidecar, ex.Message);
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The app explicitly enables SQLite WAL mode (see SqlCipherConnectionInterceptor.cs:60-63), so the -wal file can contain committed transactions not yet checkpointed into the main DB. Deleting databasePath-wal/-shm here can make the archived backup incomplete/unrestorable. Instead, archive the sidecar files alongside the moved DB (e.g., move/rename to ${archivedPath}-wal and ${archivedPath}-shm), and only delete them from the original location after they’ve been safely moved (or at least avoid deleting if the move fails).

Suggested change
// Remove WAL companion files if present. These are created when WAL mode is active
// and must be cleaned up so the fresh database starts without a stale journal.
// On Windows these files may also be locked; delete rather than move since the
// archived backup doesn't need them.
foreach (var sidecar in new[] { databasePath + "-wal", databasePath + "-shm" })
{
if (!File.Exists(sidecar)) continue;
try
{
File.Delete(sidecar);
_logger.LogInformation("Removed WAL companion file: {Sidecar}", sidecar);
}
catch (Exception ex)
{
// Non-fatal: a stale WAL without its main database is harmless.
_logger.LogWarning("Could not remove WAL companion file {Sidecar}: {Message}", sidecar, ex.Message);
// Move WAL companion files alongside the archived database if present. These are
// created when WAL mode is active and may contain committed transactions that have
// not yet been checkpointed into the main database file. For the backup to be
// complete and restorable, we archive these sidecar files together with the main DB.
var sidecars = new[]
{
new { Source = databasePath + "-wal", Destination = archivedPath + "-wal" },
new { Source = databasePath + "-shm", Destination = archivedPath + "-shm" }
};
foreach (var sidecar in sidecars)
{
if (!File.Exists(sidecar.Source)) continue;
try
{
if (File.Exists(sidecar.Destination))
{
File.Delete(sidecar.Destination);
}
File.Move(sidecar.Source, sidecar.Destination);
_logger.LogInformation("Archived WAL companion file from {Source} to {Destination}", sidecar.Source, sidecar.Destination);
}
catch (Exception ex)
{
// Non-fatal: if we can't move the sidecar, log and continue. The main
// database has already been moved, and leaving the original WAL/SHM
// next to the soon-to-be-recreated database is safer than deleting it.
_logger.LogWarning(
"Could not archive WAL companion file {Source} to {Destination}: {Message}",
sidecar.Source,
sidecar.Destination,
ex.Message);

Copilot uses AI. Check for mistakes.
Comment on lines +113 to +115
catch (IOException) when (OperatingSystem.IsWindows())
{
_logger.LogWarning("File move failed on first attempt (Windows lock), retrying after 500 ms");
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Windows retry path you catch IOException but don’t log the exception details, which makes it harder to diagnose persistent lock issues in the field. Consider capturing the exception (catch (IOException ex)) and logging it (e.g., _logger.LogWarning(ex, ...)) before the retry.

Suggested change
catch (IOException) when (OperatingSystem.IsWindows())
{
_logger.LogWarning("File move failed on first attempt (Windows lock), retrying after 500 ms");
catch (IOException ex) when (OperatingSystem.IsWindows())
{
_logger.LogWarning(ex, "File move failed on first attempt (Windows lock), retrying after 500 ms");

Copilot uses AI. Check for mistakes.
@xnodeoncode xnodeoncode merged commit 5ee6c94 into main Feb 28, 2026
1 check passed
xskcdf added a commit that referenced this pull request Feb 28, 2026
Merge pull request #34 from xnodeoncode/development
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working priority:high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants