Skip to content

feat(backend): graceful handling of DB schema version mismatch on downgrade#1342

Merged
shm11C3 merged 3 commits into
developfrom
feat/graceful-db-migration-error
Apr 11, 2026
Merged

feat(backend): graceful handling of DB schema version mismatch on downgrade#1342
shm11C3 merged 3 commits into
developfrom
feat/graceful-db-migration-error

Conversation

@shm11C3

@shm11C3 shm11C3 commented Apr 11, 2026

Copy link
Copy Markdown
Owner

Summary

When a user downgrades the app, the SQLite database may have a newer schema than the older app expects, causing a panic on startup. This adds a pre-flight schema compatibility check before Tauri starts, and shows a native dialog offering to reset the database, continue anyway, or exit — instead of crashing silently.

Related Issues

Type of Change

  • Bug fix (fix/ branch)
  • New feature (feat/ branch)
  • Refactoring (refactor/ branch)
  • Documentation (docs/ branch)
  • Dependencies update
  • Other (chore/ branch)

Screenshots / Videos

Test Plan

  • Manual testing
  • Unit tests

Checklist

  • Self-reviewed the code
  • Linting and formatting pass (npm run lint && npm run format / cargo tauri-lint && cargo tauri-fmt)
  • Tests pass (npm test / cargo tauri-test)
  • No new warnings or errors

Summary by CodeRabbit

  • New Features

    • App performs a database compatibility check at startup and defers DB-dependent initialization until the check completes.
  • Bug Fixes

    • When an incompatible database is detected, the app shows a clear “Data Compatibility Issue” dialog with options to reset & restart, continue anyway, or exit. The main window is hidden while the issue is handled to prevent crashes.
  • Tests

    • Expanded test suite covering many database compatibility scenarios.

…ngrade

When a user downgrades the app, the SQLite database may have a newer
schema than the older app expects, causing a panic on startup. This
adds a pre-flight schema compatibility check before Tauri starts, and
shows a native dialog offering to reset the database, continue anyway,
or exit — instead of crashing silently.
Copilot AI review requested due to automatic review settings April 11, 2026 20:37
@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a database preflight compatibility check that compares the app's max migration version with the existing SQLite database at startup, plus a startup service to prompt the user to reset, continue, or exit; integrates the check into application initialization and exposes a helper to compute max migration version.

Changes

Cohort / File(s) Summary
Migration utilities
src-tauri/src/infrastructure/database/migration.rs
Added pub fn get_max_migration_version() -> i64 to compute the maximum version for MigrationKind::Up.
Database module exports
src-tauri/src/infrastructure/database/mod.rs
Exported new preflight module (pub mod preflight;).
Database preflight check
src-tauri/src/infrastructure/database/preflight.rs
New module implementing check_db_compatibility() and DbStartupError; queries _sqlx_migrations, returns incompatibility when DB max successful migration > app max, and includes comprehensive tests.
Startup error service
src-tauri/src/services/db_startup_service.rs, src-tauri/src/services/mod.rs
New db_startup_service module with StartupErrorAction enum, prompt_startup_error(), reset_database_and_restart(), file-deletion helpers, error dialogs, and tests.
Application startup integration
src-tauri/src/lib.rs
Integrated preflight into startup flow: gate DB-dependent initialization and tauri_plugin_sql registration on compatibility; on error, hide main window, prompt via service, then reset/restart, continue, or exit accordingly.

Sequence Diagram

sequenceDiagram
    participant App as App Startup
    participant Preflight as Preflight Check
    participant DB as SQLite DB
    participant Svc as Startup Service
    participant UI as Dialog/UI

    App->>Preflight: check_db_compatibility()
    Preflight->>Preflight: get_max_migration_version()
    Preflight->>DB: SELECT MAX(version) FROM _sqlx_migrations WHERE success = 1
    DB-->>Preflight: db_max_version

    alt db_max_version > app_max_version
        Preflight-->>App: IncompatibleVersion
        App->>Svc: prompt_startup_error(error)
        Svc->>UI: show compatibility dialog (Reset / Continue / Exit)
        UI-->>Svc: user choice

        alt Reset
            Svc->>DB: delete database files
            Svc->>App: relaunch app (restart)
        else Continue
            Svc-->>App: Resume startup
        else Exit
            Svc->>App: exit(1)
        end
    else Compatible or first-run
        Preflight-->>App: None
        App->>App: proceed with initialization (register migrations, init controllers)
    end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐇 I sniffed the schema under moonlight,
Found versions tangled, not quite right.
A preflight check I gently sew,
Reset, continue — choose where to go.
Hoppity hope, the app takes flight! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding graceful handling of database schema version mismatches during app downgrades.
Docstring Coverage ✅ Passed Docstring coverage is 90.32% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description covers all required template sections with substantive information about the problem, solution, change type, testing approach, and completion of the implementation checklist.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/graceful-db-migration-error

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added rust Pull requests that update Rust code feature labels Apr 11, 2026
@github-actions

github-actions Bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

Rust Backend Coverage Report

Coverage Details
Filename                                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
_tests/commands/background_image_test.rs              39                 0   100.00%           6                 0   100.00%          21                 0   100.00%           0                 0         -
_tests/commands/settings_test.rs                     220                 0   100.00%          18                 0   100.00%         167                 0   100.00%           0                 0         -
commands/background_image.rs                          22                 7    68.18%          11                 5    54.55%          19                 7    63.16%           0                 0         -
commands/hardware.rs                                  66                66     0.00%          20                20     0.00%          66                66     0.00%           0                 0         -
commands/settings.rs                                 544               544     0.00%          97                97     0.00%         463               463     0.00%           0                 0         -
commands/system.rs                                     6                 6     0.00%           3                 3     0.00%           5                 5     0.00%           0                 0         -
commands/ui.rs                                        17                17     0.00%           2                 2     0.00%          13                13     0.00%           0                 0         -
commands/updater.rs                                   97                97     0.00%          15                15     0.00%          66                66     0.00%           0                 0         -
enums/error.rs                                       105                 0   100.00%           8                 0   100.00%          89                 0   100.00%           0                 0         -
enums/hardware.rs                                    188                 1    99.47%          15                 0   100.00%         114                 0   100.00%           0                 0         -
enums/settings.rs                                    415                 6    98.55%          24                 0   100.00%         279                 0   100.00%           0                 0         -
infrastructure/database/db.rs                         21                21     0.00%           2                 2     0.00%          12                12     0.00%           0                 0         -
infrastructure/database/gpu_archive.rs                51                51     0.00%           4                 4     0.00%          18                18     0.00%           0                 0         -
infrastructure/database/hardware_archive.rs           41                41     0.00%           4                 4     0.00%          21                21     0.00%           0                 0         -
infrastructure/database/migration.rs                  66                 1    98.48%          10                 0   100.00%          86                 0   100.00%           0                 0         -
infrastructure/database/preflight.rs                 288                13    95.49%          28                 1    96.43%         179                 7    96.09%           0                 0         -
infrastructure/database/process_stats.rs              41                41     0.00%           4                 4     0.00%          29                29     0.00%           0                 0         -
infrastructure/providers/linux/dmidecode.rs          229                15    93.45%          16                 3    81.25%         319                14    95.61%           0                 0         -
infrastructure/providers/linux/drm_sys.rs            205               156    23.90%          21                14    33.33%         126                93    26.19%           0                 0         -
infrastructure/providers/linux/hwmon.rs              119                94    21.01%           8                 6    25.00%          68                56    17.65%           0                 0         -
infrastructure/providers/linux/kernel.rs             165                22    86.67%          19                 2    89.47%         161                 8    95.03%           0                 0         -
infrastructure/providers/linux/lspci.rs               83                20    75.90%           8                 2    75.00%          50                11    78.00%           0                 0         -
infrastructure/providers/linux/net_sys.rs            171               171     0.00%          13                13     0.00%          93                93     0.00%           0                 0         -
infrastructure/providers/linux/procfs.rs             261                24    90.80%          25                 3    88.00%         222                19    91.44%           0                 0         -
infrastructure/providers/sysinfo_provider.rs          54                54     0.00%           2                 2     0.00%          45                45     0.00%           0                 0         -
lib.rs                                               247               247     0.00%           6                 6     0.00%         138               138     0.00%           0                 0         -
main.rs                                                3                 3     0.00%           1                 1     0.00%           3                 3     0.00%           0                 0         -
models/hardware.rs                                   292                 0   100.00%          19                 0   100.00%         175                 0   100.00%           0                 0         -
models/hardware_archive.rs                             3                 0   100.00%           1                 0   100.00%           7                 0   100.00%           0                 0         -
models/settings.rs                                   301                 0   100.00%          17                 0   100.00%         264                 0   100.00%           0                 0         -
platform/factory.rs                                   18                18     0.00%           4                 4     0.00%          15                15     0.00%           0                 0         -
platform/linux/cache.rs                               53                53     0.00%           4                 4     0.00%          38                38     0.00%           0                 0         -
platform/linux/gpu.rs                                143               143     0.00%          14                14     0.00%         105               105     0.00%           0                 0         -
platform/linux/memory.rs                              43                43     0.00%           6                 6     0.00%          41                41     0.00%           0                 0         -
platform/linux/mod.rs                                 34                34     0.00%          11                11     0.00%          70                70     0.00%           0                 0         -
platform/linux/network.rs                              4                 4     0.00%           1                 1     0.00%           4                 4     0.00%           0                 0         -
services/archive_service.rs                         1234               155    87.44%          93                15    83.87%         694               135    80.55%           0                 0         -
services/background_image_service.rs                 165                96    41.82%          16                10    37.50%          93                59    36.56%           0                 0         -
services/cpu_service.rs                               32                32     0.00%           4                 4     0.00%          15                15     0.00%           0                 0         -
services/db_startup_service.rs                       188                87    53.72%          10                 3    70.00%         114                58    49.12%           0                 0         -
services/gpu_service.rs                               37                37     0.00%          10                10     0.00%          31                31     0.00%           0                 0         -
services/hardware_service.rs                          67                67     0.00%           5                 5     0.00%          43                43     0.00%           0                 0         -
services/language_service.rs                         101                 0   100.00%          18                 0   100.00%          57                 0   100.00%           0                 0         -
services/memory_service.rs                            22                22     0.00%           4                 4     0.00%          15                15     0.00%           0                 0         -
services/monitoring_service.rs                      1114               161    85.55%          75                19    74.67%         574               104    81.88%           0                 0         -
services/motherboard_service.rs                       10                10     0.00%           3                 3     0.00%           7                 7     0.00%           0                 0         -
services/network_service.rs                            9                 9     0.00%           1                 1     0.00%           7                 7     0.00%           0                 0         -
services/process_service.rs                           86                86     0.00%           5                 5     0.00%          50                50     0.00%           0                 0         -
services/settings_service.rs                         338               158    53.25%          34                16    52.94%         288               148    48.61%           0                 0         -
services/system_service.rs                            22                22     0.00%           2                 2     0.00%          12                12     0.00%           0                 0         -
services/ui_service.rs                                45                45     0.00%           8                 8     0.00%          36                36     0.00%           0                 0         -
utils/color.rs                                        66                 1    98.48%           4                 0   100.00%          26                 0   100.00%           0                 0         -
utils/file.rs                                        224                 5    97.77%          14                 0   100.00%         144                 4    97.22%           0                 0         -
utils/formatter.rs                                   195                 8    95.90%          16                 0   100.00%         160                12    92.50%           0                 0         -
utils/ip.rs                                           65                 0   100.00%           5                 0   100.00%          33                 0   100.00%           0                 0         -
utils/logger.rs                                       71                71     0.00%           1                 1     0.00%          38                38     0.00%           0                 0         -
utils/rounding.rs                                     68                 0   100.00%           7                 0   100.00%          41                 0   100.00%           0                 0         -
utils/tauri.rs                                       138                 0   100.00%          17                 0   100.00%          82                 0   100.00%           0                 0         -
workers/hardware_archive.rs                           52                52     0.00%           6                 6     0.00%          36                36     0.00%           0                 0         -
workers/mod.rs                                        24                24     0.00%           2                 2     0.00%          16                16     0.00%           0                 0         -
workers/system_monitor.rs                            261                97    62.84%          18                 6    66.67%         150                66    56.00%           0                 0         -
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                               9289              3258    64.93%         845               369    56.33%        6353              2352    62.98%           0                 0         -

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a backend preflight check to detect SQLite schema version mismatches (e.g., after downgrading), and surfaces a native startup dialog to avoid crashing on launch.

Changes:

  • Added DB schema compatibility preflight logic that inspects _sqlx_migrations vs the app’s max migration version.
  • Introduced a native startup dialog service with options to reset+restart, continue, or exit.
  • Made SQL plugin registration and several startup routines conditional on DB compatibility.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src-tauri/src/services/mod.rs Exposes the new DB startup dialog service module.
src-tauri/src/services/db_startup_service.rs Implements the native dialog + DB file deletion + restart behavior (with unit tests).
src-tauri/src/lib.rs Runs the preflight check and conditionally initializes the SQL plugin and startup workers/UI.
src-tauri/src/infrastructure/database/preflight.rs New preflight implementation that queries max successful migration version (with tests).
src-tauri/src/infrastructure/database/mod.rs Re-exports the new preflight module.
src-tauri/src/infrastructure/database/migration.rs Adds get_max_migration_version() helper and test.

Comment thread src-tauri/src/lib.rs
Comment thread src-tauri/src/lib.rs Outdated
Comment thread src-tauri/src/services/db_startup_service.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src-tauri/src/lib.rs (1)

138-208: ⚠️ Potential issue | 🔴 Critical

ContinueAnyway is currently a dead-end startup path.

At Lines 138-189 and 243-249, all window/event/worker initialization and SQL plugin registration are gated on is_db_ok. When the dialog returns ContinueAnyway at Line 204, this branch does not resume any of that work or re-show the hidden "main" window, so the app keeps running in the background with no usable UI. Either remove this action or explicitly continue the non-DB startup flow from here.

Also applies to: 243-249

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/lib.rs` around lines 138 - 208, The ContinueAnyway path
currently returns without resuming the startup sequence guarded by is_db_ok,
leaving the app running headless; update the ContinueAnyway branch in the thread
spawned for db_startup_service::prompt_startup_error so it re-runs the same
post-DB-success initialization (re-show the "main" window and execute the code
that runs when is_db_ok is true): call the UI init (commands::ui::init), mount
events (builder.mount_events), register SQL plugin/attachments, set up
SystemMonitorController::setup and HardwareArchiveController::setup and store
them into app.state::<workers::WorkersState>() (monitor and hw_archive), and
re-enable scheduled_data_deletion (tauri::async_runtime::spawn of
batch_delete_old_data) — or refactor that whole block into a helper function
(e.g., init_after_db_ok) and invoke it from both the is_db_ok branch and the
ContinueAnyway arm to avoid duplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src-tauri/src/services/db_startup_service.rs`:
- Around line 70-76: The restart code currently calls std::env::current_exe()
and .spawn().expect(...) which will panic on failure; instead, change the
recover-and-restart path in db_startup_service.rs to handle errors from
current_exe and Command::new(...).spawn() gracefully: remove both expect()
calls, propagate or match on the Result from current_exe() and spawn(), and on
error log/report the failure and show the same user-facing actionable error flow
used by the delete-failure branch (e.g., show a dialog or return an Err) rather
than aborting; update references around exe_path, args, Command::new and spawn
to use non-panicking error handling and surface the error message to the user or
caller.
- Around line 1-7: The service currently performs UI dialogs and filesystem
cleanup directly (see imports of tauri_plugin_dialog and use of Path) which must
be moved to an infrastructure abstraction: extract the recovery I/O (dialog
display + cleanup operations) into a new infrastructure component (e.g.,
infrastructure::recovery::RecoveryIO) that implements a trait (e.g.,
RecoveryIoTrait) with methods like confirm_recovery_dialog(...) and
remove_recovery_files(path: &Path) and implement the platform-specific Tauri
dialog + fs logic there; then change db_startup_service.rs to depend on the
trait (injected via factory or constructor) and replace direct
tauri_plugin_dialog and Path-based cleanup calls with calls to the trait
methods, keeping DbStartupError usage unchanged so only the I/O implementation
moves to infrastructure.

---

Outside diff comments:
In `@src-tauri/src/lib.rs`:
- Around line 138-208: The ContinueAnyway path currently returns without
resuming the startup sequence guarded by is_db_ok, leaving the app running
headless; update the ContinueAnyway branch in the thread spawned for
db_startup_service::prompt_startup_error so it re-runs the same post-DB-success
initialization (re-show the "main" window and execute the code that runs when
is_db_ok is true): call the UI init (commands::ui::init), mount events
(builder.mount_events), register SQL plugin/attachments, set up
SystemMonitorController::setup and HardwareArchiveController::setup and store
them into app.state::<workers::WorkersState>() (monitor and hw_archive), and
re-enable scheduled_data_deletion (tauri::async_runtime::spawn of
batch_delete_old_data) — or refactor that whole block into a helper function
(e.g., init_after_db_ok) and invoke it from both the is_db_ok branch and the
ContinueAnyway arm to avoid duplication.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 16f03013-1008-4486-b11b-1d3ae4a6ab59

📥 Commits

Reviewing files that changed from the base of the PR and between 75d5b41 and ff6d7ea.

📒 Files selected for processing (6)
  • src-tauri/src/infrastructure/database/migration.rs
  • src-tauri/src/infrastructure/database/mod.rs
  • src-tauri/src/infrastructure/database/preflight.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/services/db_startup_service.rs
  • src-tauri/src/services/mod.rs

Comment thread src-tauri/src/services/db_startup_service.rs
Comment thread src-tauri/src/services/db_startup_service.rs Outdated
- Move UI/monitor initialization outside the is_db_ok gate so real-time
  monitoring works even when DB is incompatible
- Show the main window when user chooses "Continue Anyway" instead of
  leaving the app headless
- Replace expect() with error dialogs in reset_database_and_restart to
  avoid panicking in the recovery path
- Extract show_error_dialog helper to reduce duplication

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
src-tauri/src/services/db_startup_service.rs (1)

1-6: ⚠️ Potential issue | 🟠 Major

Move the recovery I/O out of services/.

This module still owns Tauri dialog calls, filesystem deletion, and process restart logic, so the service layer is doing UI/OS I/O instead of delegating it behind a platform/infrastructure abstraction. Please keep this layer focused on choosing the recovery action and push the actual dialog/fs/process work behind a trait/factory boundary.

As per coding guidelines, "Infrastructure code for OS APIs, database, and external I/O should be in src-tauri/src/infrastructure/**" and "Services layer must implement business logic and use Factory pattern for platform abstraction".

Also applies to: 23-39, 56-105

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/services/db_startup_service.rs` around lines 1 - 6, The
db_startup_service.rs currently performs UI and OS I/O (Tauri dialogs,
filesystem deletion, and process restart) inside the service; refactor by
extracting a platform/infrastructure trait (e.g., RecoveryPlatform or
DbRecoveryHandler) with methods like show_recovery_dialog(...),
delete_db_files(Path), and restart_process() implemented under
src-tauri/src/infrastructure/**, then update the service (functions in
db_startup_service.rs that determine recovery actions) to call only the trait
methods to choose an action and return/dispatch the selected recovery enum
instead of performing dialog/fs/process work directly; keep decision logic
(choose recovery action) in the service and move all Tauri/Dialog/Path/Process
calls into the new infrastructure implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src-tauri/src/services/db_startup_service.rs`:
- Around line 1-6: The db_startup_service.rs currently performs UI and OS I/O
(Tauri dialogs, filesystem deletion, and process restart) inside the service;
refactor by extracting a platform/infrastructure trait (e.g., RecoveryPlatform
or DbRecoveryHandler) with methods like show_recovery_dialog(...),
delete_db_files(Path), and restart_process() implemented under
src-tauri/src/infrastructure/**, then update the service (functions in
db_startup_service.rs that determine recovery actions) to call only the trait
methods to choose an action and return/dispatch the selected recovery enum
instead of performing dialog/fs/process work directly; keep decision logic
(choose recovery action) in the service and move all Tauri/Dialog/Path/Process
calls into the new infrastructure implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 0d512595-7173-4119-ac6c-0ace839e43f7

📥 Commits

Reviewing files that changed from the base of the PR and between ff6d7ea and 8d5d3c9.

📒 Files selected for processing (2)
  • src-tauri/src/lib.rs
  • src-tauri/src/services/db_startup_service.rs

@shm11C3 shm11C3 merged commit 8510c83 into develop Apr 11, 2026
48 checks passed
@shm11C3 shm11C3 deleted the feat/graceful-db-migration-error branch April 11, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants