Skip to content

fix(prefs): 解析失败时逐字段抢救+备份,避免升级改 schema 静默清空设置#791

Open
bigsongeth wants to merge 1 commit into
Open-Less:betafrom
bigsongeth:feat/prefs-salvage
Open

fix(prefs): 解析失败时逐字段抢救+备份,避免升级改 schema 静默清空设置#791
bigsongeth wants to merge 1 commit into
Open-Less:betafrom
bigsongeth:feat/prefs-salvage

Conversation

@bigsongeth

@bigsongeth bigsongeth commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

User description

问题

preferences.json严格反序列化:容器级 #[serde(default)] 能容忍「缺字段」(老文件读新版本 OK),但扛不住「字段仍在、值非法」——当某次版本更新改了 prefs 的 schema(如重命名枚举变体、改字段类型),老用户文件里的旧值在新版本里不再合法,整份 UserPreferences 解析失败 → 旧代码 unwrap_or_else(default) 静默回落默认值,用户随手改一项就把历史设置(热键、模型选择、风格…)永久覆盖成默认。

改动

read_preferences 严格解析失败时,不再静默重置,而是:

  1. 原样备份坏文件为 preferences.corrupt-<ts>.json,永不销毁;
  2. 逐字段抢救UserPreferences::salvage_from_json_bytes)——把 JSON 当对象逐 key 试解析,只把值非法的字段回默认,其余仍合法的设置全部保留
  3. 写回抢救结果,得到干净可解析的文件。

新增测试 salvage_preserves_valid_fields_when_one_value_is_invalid:构造 defaultMode 非法但 dictationHotkey / activeAsrProvider 合法的文件,断言严格解析必失败、抢救后热键与 ASR 保住、仅非法字段回默认。

适用性

面向任何跨 schema 变更升级的用户,不局限于某种安装方式——只要某次发布改了 prefs 结构,此改动就能避免老用户设置被整份清空。维护者若认为发布流程已通过 serde default 覆盖此风险,可自行取舍。

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com


PR Type

Bug fix, Enhancement


Description

  • Backup unparseable preferences file before salvage

  • Salvage valid fields by trying each JSON key individually

  • Write back salvaged preferences to disk for clean future reads

  • Add test verifying valid fields preserved when one field is invalid


Diagram Walkthrough

flowchart LR
  A["Start read_preferences"] --> B{"Parse strict?"}
  B -- "Success" --> C["Normal path"]
  B -- "Fail" --> D["Backup original to .corrupt file"]
  D --> E["Salvage: try each key"]
  E --> F["Write salvaged back"]
  F --> G["Return salvaged preferences"]
Loading

File Walkthrough

Relevant files
Error handling
preferences.rs
Handle parse failure with backup and salvage                         

openless-all/app/src-tauri/src/persistence/preferences.rs

  • Added backup of unparseable preferences file to .corrupt-.json
  • Modified read_preferences to call salvage on parse failure instead of
    silently returning default
  • Introduced backup_unparseable_preferences helper function
+50/-2   
Enhancement
types.rs
Add per-field salvage logic to UserPreferences                     

openless-all/app/src-tauri/src/types.rs

  • Added salvage_from_json_bytes method to UserPreferences
  • Implements per-field fallback: drops only invalid values while
    preserving valid ones
  • Added test salvage_preserves_valid_fields_when_one_value_is_invalid
+57/-0   

@github-actions

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant