libnyanpasu/clash-nyanpasu · error

failed to serialize config: {e}

Error message

failed to serialize config: {e}

What it means

This error is raised during hotkey-to-KV storage migration when serde_yaml cannot serialize the modified config map back to YAML before it is atomically written to disk. It wraps the underlying serde_yaml error, so the message includes the serializer's own diagnostics. It indicates the in-memory config value contains data that cannot be represented as YAML (rare, e.g. non-string map keys of unsupported types or an IO-derived value that fails serialization).

Source

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

                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 {
    STEPS.last().map(|step| step.revision()).unwrap_or_default()
}

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Read the wrapped serde_yaml message in {e} to identify the offending key/value
  2. Open the config YAML file at config_path and fix or remove the invalid key/value manually
  3. Delete or rename the config file so the migration recreates a clean default (backup first)
  4. Verify the config is parsed into a serde_yaml::Mapping/String-keyed map rather than a generic Value with non-string keys
  5. Report a bug if stock config data triggers it — the migration should be lossless for valid YAML

Example fix

// before
let new_config = serde_yaml::to_string(&config)
    .map_err(|e| anyhow::anyhow!("failed to serialize config: {e}"))?;
// after
let new_config = serde_yaml::to_string(&config).map_err(|e| {
    tracing::error!("hotkey migration: serialize failed: {e}; config keys: {:?}", config.keys().collect::<Vec<_>>());
    anyhow::anyhow!("failed to serialize config: {e}")
})?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn is_yaml_serializable(v: &serde_yaml::Value) -> bool {
    match v {
        serde_yaml::Value::Mapping(m) => m.iter().all(|(k, val)| {
            matches!(k, serde_yaml::Value::String(_) | serde_yaml::Value::Number(_) | serde_yaml::Value::Bool(_))
                && is_yaml_serializable(val)
        }),
        serde_yaml::Value::Sequence(s) => s.iter().all(is_yaml_serializable),
        serde_yaml::Value::Tagged(t) => is_yaml_serializable(&t.value),
        _ => true,
    }
}

Type guard

fn has_string_keys(m: &serde_yaml::Mapping) -> bool {
    m.keys().all(|k| matches!(k, serde_yaml::Value::String(_)))
}

Try / catch

match serde_yaml::to_string(&config) {
    Ok(yaml) => atomic_write(&config_path, yaml.as_bytes())?,
    Err(e) => {
        log::error!("config serialization failed: {e}; aborting migration without writing");
        return Err(anyhow::anyhow!("failed to serialize config: {e}"));
    }
}

Prevention

When it happens

Trigger: Calling the hotkey migration step in run() after config.remove(&hotkeys_key) when serde_yaml::to_string(&config) fails on the loaded YAML mapping — typically because the config contains keys or values serde_yaml cannot serialize (e.g. non-string keys not representable in YAML 1.1, or invalid Unicode scalars in values).

Common situations: A user's hotkey config file was hand-edited or written by an older/buggy version producing YAML with unusual key types; a corrupted config file loaded into a mapping with values the serializer rejects; platform-specific hotkey strings with invalid characters injected into the map.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


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