{"record":{"id":"4dc8a0c7169a7124","repo":"jlcodes99/cockpit-tools","slug":"error-4dc8a0","errorCode":null,"errorMessage":"保存失败: {}","messagePattern":"保存失败: \\{\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cockpit-core/src/modules/import.rs","lineNumber":682,"sourceCode":"                            if let Ok(acc) =\n                                modules::account::update_account_tags(&new_account.id, entry.tags)\n                            {\n                                new_account = acc;\n                            }\n                        }\n                        if let Some(notes) = entry.notes {\n                            if let Ok(acc) =\n                                modules::account::update_account_notes(&new_account.id, notes)\n                            {\n                                new_account = acc;\n                            }\n                        }\n                        modules::logger::log_info(&format!(\"导入账号成功: {}\", new_account.email));\n                        imported.push(new_account);\n                    }\n                    Err(e) => {\n                        let msg = format!(\"保存失败: {}\", e);\n                        modules::logger::log_error(&format!(\"保存账号失败 {}: {}\", email, msg));\n                        failed.push(FileImportFailure { email, error: msg });\n                    }\n                }\n            }\n            Err(e) => {\n                let label = entry.email.as_deref().unwrap_or(\"unknown\").to_string();\n                let msg = format!(\"Token 刷新失败: {}\", e);\n                modules::logger::log_error(&format!(\"{}: {}\", label, msg));\n                failed.push(FileImportFailure {\n                    email: label,\n                    error: msg,\n                });\n            }\n        }\n    }\n\n    modules::logger::log_info(&format!(\n        \"文件导入完成，成功 {} 个，失败 {} 个\",","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/crates/cockpit-core/src/modules/import.rs#L664-L700","documentation":"Produced in import_from_files_logic after a refresh_token from an imported file was successfully exchanged, but upsert_account failed to persist the resulting account. The underlying storage error `e` is wrapped as \"保存失败: {}\" and recorded per-email in the FileImportFailure list; the import continues with other entries.","triggerScenarios":"Calling import_from_files_logic (file import) where modules::upsert_account returns Err — e.g. storage/serialization failure, disk I/O error, account store lock contention, or an account constraint violation for the resolved email.","commonSituations":"Accounts file locked or read-only on disk; corrupted local account database; duplicate/invalid email key that the store rejects; running out of disk space; concurrent import sessions racing on the same account record.","solutions":["Read the inner error after '保存失败: ' to identify the storage-layer cause (I/O, serialization, or constraint).","Check disk space and that the account storage files/database are writable and not locked by another Cockpit instance.","Retry the import; failed entries are reported individually so successfully imported accounts are not duplicated.","If a duplicate email is the cause, delete or update the existing account first, then re-import.","Back up and repair/recreate a corrupted account store if serialization errors persist."],"exampleFix":"// before: ignoring per-entry failures\nlet result = import_from_files_logic(paths).await?;\n// after: inspect and retry only failed entries\nlet result = import_from_files_logic(paths).await?;\nfor f in &result.failed {\n    eprintln!(\"import failed for {}: {}\", f.email, f.error);\n}\nif !result.failed.is_empty() {\n    free_disk_or_unlock_store();\n    retry_failed_imports(&result.failed)?;\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight storage checks before importing\nfn storage_ready() -> Result<(), String> {\n    let dir = account_store_dir();\n    if !dir.exists() { std::fs::create_dir_all(&dir).map_err(|e| e.to_string())?; }\n    let probe = dir.join(\".write_probe\");\n    std::fs::write(&probe, b\"ok\").map_err(|e| format!(\"store not writable: {}\", e))?;\n    std::fs::remove_file(&probe).map_err(|e| e.to_string())\n}","typeGuard":"fn is_duplicate_account_error(err: &str) -> bool {\n    err.contains(\"duplicate\") || err.contains(\"已存在\") || err.contains(\"unique\")\n}","tryCatchPattern":"let result = import_from_files_logic(&paths).await?; // per-entry failures land in result.failed\nfor f in &result.failed {\n    if let Some(storage_err) = f.error.strip_prefix(\"保存失败: \") {\n        log::error!(\"save failed for {}: {}\", f.email, storage_err);\n    }\n}\nif !result.failed.is_empty() { offer_retry_of_failed(&result.failed); }","preventionTips":["Verify disk space and store writability before starting a bulk import.","Run only one import at a time to avoid store lock contention.","Check result.failed after every import instead of assuming full success.","Back up the account store before large imports.","Resolve duplicate emails before re-importing the same file."],"tags":["import","persistence","storage","file-import"],"backgroundTag":"account-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"}