{"record":{"id":"160d634305d5e599","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-parse-config-e-160d63","errorCode":null,"errorMessage":"failed to parse config: {e}","messagePattern":"failed to parse config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/migration/modules/storage.rs","lineNumber":30,"sourceCode":"\nconst HOTKEYS_KEY: &str = \"hotkeys\";\n\npub struct StorageMigrator;\n\nimpl ModuleMigrator for StorageMigrator {\n    fn module(&self) -> &'static str {\n        \"storage\"\n    }\n\n    fn detect_baseline(&self, ctx: &Ctx) -> anyhow::Result<u64> {\n        let config_path = ctx.nyanpasu_config_path();\n        if !config_path.exists() {\n            return Ok(current_revision());\n        }\n\n        let raw = std::fs::read_to_string(&config_path)?;\n        let config: Mapping = serde_yaml::from_str(&raw)\n            .map_err(|e| anyhow::anyhow!(\"failed to parse config: {e}\"))?;\n        if config\n            .get(HOTKEYS_KEY)\n            .is_some_and(|value| value.as_sequence().is_some())\n        {\n            Ok(0)\n        } else {\n            Ok(current_revision())\n        }\n    }\n\n    fn steps(&self) -> &'static [&'static dyn MigrationStep] {\n        &STEPS\n    }\n}\n\n#[derive(Debug, Clone, Copy)]\npub struct MigrateHotkeysToKv;\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/migration/modules/storage.rs#L12-L48","documentation":"detect_baseline reads the hotkey config.yaml to decide which migration baseline the installation is at. It parses the file into a serde_yaml Mapping; if parsing fails, this error is returned instead of a revision number, so the migration framework cannot determine the starting point.","triggerScenarios":"config.yaml exists but serde_yaml::from_str::<Mapping> fails: invalid YAML syntax, top-level non-mapping document, duplicate keys, BOM/non-UTF8 bytes, or truncation from a previous bad write.","commonSituations":"User hand-edited config.yaml and broke syntax; corrupt file from an old version or crash; encoding issues from external editors.","solutions":["Fix the YAML syntax error at the line/column reported in {e}.","Restore config.yaml from backup or let the app regenerate defaults by moving the corrupt file aside.","Validate externally with a YAML parser before re-running migration.","Ensure the file is UTF-8 without BOM, spaces-only indentation."],"exampleFix":"// before\nlet config: Mapping = serde_yaml::from_str(&raw)\n    .map_err(|e| anyhow::anyhow!(\"failed to parse config: {e}\"))?;\n// after\nlet config: Mapping = serde_yaml::from_str(&raw)\n    .with_context(|| format!(\"failed to parse config at {} for baseline detection\", config_path.display()))?;","handlingStrategy":"validation","validationCode":"fn config_yaml_ok(path: &Path) -> Result<(), String> {\n    let raw = std::fs::read_to_string(path).map_err(|e| e.to_string())?;\n    serde_yaml::from_str::<serde_yaml::Mapping>(&raw)\n        .map(|_| ())\n        .map_err(|e| format!(\"{}: {e}\", path.display()))\n}","typeGuard":"fn is_valid_config_yaml(raw: &str) -> bool {\n    serde_yaml::from_str::<serde_yaml::Mapping>(raw).is_ok()\n}","tryCatchPattern":"let config: Mapping = match serde_yaml::from_str(&raw) {\n    Ok(c) => c,\n    Err(e) => {\n        eprintln!(\"cannot detect baseline, config.yaml invalid: {e}\");\n        eprintln!(\"fix or restore config.yaml, then re-run migration\");\n        return Err(anyhow::anyhow!(\"failed to parse config: {e}\"));\n    }\n};","preventionTips":["Validate config.yaml with a linter after any manual edit","Keep edits in the UI where possible; treat raw YAML edits as risky","Save as UTF-8 (no BOM) with spaces-only indentation","Maintain backups of config.yaml before upgrading versions"],"tags":["yaml","migration","config","parse-error","hotkeys"],"backgroundTag":"yaml-parse-error","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"}