libnyanpasu/clash-nyanpasu · error

failed to save hotkeys: {e}

Error message

failed to save hotkeys: {e}

What it means

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.

Source

Thrown at backend/tauri/src/core/migration/modules/storage.rs:104

            return Ok(());
        };

        let hotkey_strings: Vec<String> = hotkeys
            .iter()
            .filter_map(|value| value.as_str().map(ToString::to_string))
            .collect();

        if !hotkey_strings.is_empty() {
            let storage_path = ctx.storage_path();
            if let Some(parent) = storage_path.parent() {
                std::fs::create_dir_all(parent)?;
            }
            let storage = Storage::try_new(&storage_path)
                .map_err(|e| anyhow::anyhow!("failed to open storage: {e}"))?;

            storage
                .set_item("hotkeys", &hotkey_strings)
                .map_err(|e| anyhow::anyhow!("failed to save hotkeys: {e}"))?;

            // Note: registration is intentionally NOT done here. This migration
            // runs in a separate `migrate` subprocess with no Tauri app handle, so
            // `Hotkey::update` would fail; `Hotkey::init` reads the migrated value
            // from KV storage at app startup instead.
            tracing::info!("migrated {} hotkeys to KV storage", hotkey_strings.len());
        }

        config.remove(&hotkeys_key);
        let new_config = serde_yaml::to_string(&config)
            .map_err(|e| anyhow::anyhow!("failed to serialize config: {e}"))?;
        crate::core::migration::fs::atomic_write(&config_path, new_config.as_bytes())?;

        Ok(())
    }
}

fn current_revision() -> u64 {

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Free disk space / resolve I/O errors on the volume holding the storage path, then re-run migration.
  2. Check {e}: if it indicates serialization failure, verify the hotkey_strings values are plain strings and the storage crate versions match.
  3. Restart after closing other app instances to rule out lock contention, retrying the migration.
  4. 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).

Example fix

// before
storage.set_item("hotkeys", &hotkey_strings)
    .map_err(|e| anyhow::anyhow!("failed to save hotkeys: {e}"))?;
// after
storage.set_item("hotkeys", &hotkey_strings)
    .with_context(|| "failed to save hotkeys to KV storage — check disk space and storage DB integrity")?;
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

if let Err(e) = storage.set_item("hotkeys", &hotkey_strings) {
    eprintln!("KV write failed, config.yaml untouched — check disk space/DB integrity: {e}");
    return Err(anyhow::anyhow!("failed to save hotkeys: {e}"));
} // safe to retry after remediation since the source file was not modified

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/2a3b4c2ced436723. Report an issue: GitHub.