{"record":{"id":"1b8fc354bf267305","repo":"jlcodes99/cockpit-tools","slug":"syncsettings","errorCode":null,"errorMessage":"[SyncSettings] 保存合并后的配置失败: {}","messagePattern":"\\[SyncSettings\\] 保存合并后的配置失败: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src-tauri/src/lib.rs","lineNumber":348,"sourceCode":"            }\n\n            // 启动时同步设置合并（移至后台线程，不阻塞窗口显示）\n            std::thread::spawn(|| {\n                let current_config = modules::config::get_user_config();\n                if let Some(merged_language) = modules::sync_settings::merge_setting_on_startup(\n                    \"language\",\n                    &current_config.language,\n                    None,\n                ) {\n                    info!(\n                        \"[SyncSettings] 启动时合并语言设置: {} -> {}\",\n                        current_config.language, merged_language\n                    );\n                    if let Err(e) = modules::config::patch_user_config(|config| {\n                        config.language = merged_language;\n                        Ok(())\n                    }) {\n                        logger::log_error(&format!(\"[SyncSettings] 保存合并后的配置失败: {}\", e));\n                    }\n                }\n            });\n\n            // 启动 WebSocket 服务（使用 Tauri 的 async runtime）\n            tauri::async_runtime::spawn(async {\n                modules::websocket::start_server().await;\n            });\n\n            // 启动网页查询服务（网络服务配置中的独立模块）\n            tauri::async_runtime::spawn(async {\n                modules::web_report::start_server().await;\n            });\n\n            tauri::async_runtime::spawn(async {\n                modules::codex_local_access::restore_local_access_gateway().await;\n            });\n","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src-tauri/src/lib.rs#L330-L366","documentation":"During app setup in src-tauri/src/lib.rs run(), after merging default config language with system language, the code persists the merged language via modules::config::patch_user_config; failure is logged as '[SyncSettings] 保存合并后的配置失败: {e}'. It is non-fatal: startup continues, but the merged language is not persisted, so it will be re-derived (and possibly re-prompted) on next launch.","triggerScenarios":"patch_user_config returns Err while writing config.language: config file read/parse failure, write permission denied, file locked, or disk full during first-launch language sync.","commonSituations":"First launch on a system where the config directory doesn't exist or isn't writable; config JSON corrupted from a previous crash; multiple app instances racing on the config file at startup.","solutions":["Read the inner e for the underlying config I/O or parse error.","Ensure the user config directory exists and is writable before app setup (create dirs, fix permissions).","If the config file is corrupted JSON, back it up and let the app regenerate defaults.","Retry launching the app after closing other instances that may lock the config file."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Before launch, ensure config dir is writable\nconst ok = await invoke('ensure_config_dir_writable').catch(() => false);\nif (!ok) console.warn('config dir not writable; language sync will be skipped');","typeGuard":"function isSupportedLanguage(l: unknown): l is 'zh-CN' | 'en-US' {\n  return l === 'zh-CN' || l === 'en-US';\n}","tryCatchPattern":"try {\n  await invoke('patch_user_config', { patch: { language: mergedLanguage } });\n} catch (e) {\n  // fall back to in-memory language only; do not block startup\n  console.warn('language not persisted; will re-merge on next launch', e);\n}","preventionTips":["Create the config directory with correct permissions during install","Parse config defensively and regenerate on corruption","Serialize config writes during startup initialization","Treat language persistence as best-effort, never fatal to startup"],"tags":["config","startup","persistence","tauri","i18n"],"backgroundTag":"config-save-failed","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}