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
- Read the wrapped serde_yaml message in {e} to identify the offending key/value
- Open the config YAML file at config_path and fix or remove the invalid key/value manually
- Delete or rename the config file so the migration recreates a clean default (backup first)
- Verify the config is parsed into a serde_yaml::Mapping/String-keyed map rather than a generic Value with non-string keys
- 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
- Keep config maps string-keyed when loading into generic Values
- Validate hand-edited YAML config files with a linter before the app reads them
- Back up the config file before running migrations
- Never inject raw non-UTF8 or exotic-typed data into the config map
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
- unrecognized typed config migration state: existing {} is ne
- failed to serialize migrated profiles: {e}
- failed to serialize profiles: {e}
- failed to parse config: {e}
- cannot repair typed clash config before split_legacy_config
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/52145d62b22e4769.
Report an issue: GitHub.