{"record":{"id":"2a3b4c2ced436723","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-save-hotkeys-e","errorCode":null,"errorMessage":"failed to save hotkeys: {e}","messagePattern":"failed to save hotkeys: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/migration/modules/storage.rs","lineNumber":104,"sourceCode":"            return Ok(());\n        };\n\n        let hotkey_strings: Vec<String> = hotkeys\n            .iter()\n            .filter_map(|value| value.as_str().map(ToString::to_string))\n            .collect();\n\n        if !hotkey_strings.is_empty() {\n            let storage_path = ctx.storage_path();\n            if let Some(parent) = storage_path.parent() {\n                std::fs::create_dir_all(parent)?;\n            }\n            let storage = Storage::try_new(&storage_path)\n                .map_err(|e| anyhow::anyhow!(\"failed to open storage: {e}\"))?;\n\n            storage\n                .set_item(\"hotkeys\", &hotkey_strings)\n                .map_err(|e| anyhow::anyhow!(\"failed to save hotkeys: {e}\"))?;\n\n            // Note: registration is intentionally NOT done here. This migration\n            // runs in a separate `migrate` subprocess with no Tauri app handle, so\n            // `Hotkey::update` would fail; `Hotkey::init` reads the migrated value\n            // from KV storage at app startup instead.\n            tracing::info!(\"migrated {} hotkeys to KV storage\", hotkey_strings.len());\n        }\n\n        config.remove(&hotkeys_key);\n        let new_config = serde_yaml::to_string(&config)\n            .map_err(|e| anyhow::anyhow!(\"failed to serialize config: {e}\"))?;\n        crate::core::migration::fs::atomic_write(&config_path, new_config.as_bytes())?;\n\n        Ok(())\n    }\n}\n\nfn current_revision() -> u64 {","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/migration/modules/storage.rs#L86-L122","documentation":"The storage opened successfully, but Storage::set_item(\"hotkeys\", &hotkey_strings) failed while persisting the migrated hotkeys. This is a write failure inside the KV storage backend (serialization of the value or the underlying DB write), and it aborts the migration leaving config.yaml unmodified.","triggerScenarios":"set_item errors because the value cannot be serialized into the storage format, the DB write fails mid-transaction (disk full, I/O error), the storage handle became invalid, or the file was locked/deleted after open by an external process.","commonSituations":"Disk-full or quota exceeded on the app-data volume; antivirus interfering after file creation; corrupt DB page surfaces on write; storage backend version mismatch on the serialized value format.","solutions":["Free disk space / resolve I/O errors on the volume holding the storage path, then re-run migration.","Check {e}: if it indicates serialization failure, verify the hotkey_strings values are plain strings and the storage crate versions match.","Restart after closing other app instances to rule out lock contention, retrying the migration.","If the DB is corrupt, back up and remove the storage file so a fresh one is created (config.yaml remains the source of truth and can be re-migrated)."],"exampleFix":"// before\nstorage.set_item(\"hotkeys\", &hotkey_strings)\n    .map_err(|e| anyhow::anyhow!(\"failed to save hotkeys: {e}\"))?;\n// after\nstorage.set_item(\"hotkeys\", &hotkey_strings)\n    .with_context(|| \"failed to save hotkeys to KV storage — check disk space and storage DB integrity\")?;","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"if let Err(e) = storage.set_item(\"hotkeys\", &hotkey_strings) {\n    eprintln!(\"KV write failed, config.yaml untouched — check disk space/DB integrity: {e}\");\n    return Err(anyhow::anyhow!(\"failed to save hotkeys: {e}\"));\n} // safe to retry after remediation since the source file was not modified","preventionTips":["Ensure sufficient free disk space before running migrations","Verify hotkey values are plain strings compatible with the storage serializer","Keep storage backend crate versions aligned between writer and reader","Back up the KV database before migration and verify the write by reading the item back afterwards"],"tags":["storage","kv-database","migration","hotkeys","write-failed"],"backgroundTag":"database-write-failed","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}