{"record":{"id":"14e9f434b9ae67a8","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-parse-profiles-e","errorCode":null,"errorMessage":"failed to parse profiles: {e}","messagePattern":"failed to parse profiles: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/migration/modules/profiles.rs","lineNumber":34,"sourceCode":"static CLEAN_SCHEMA: MigrateProfilesCleanSchema = MigrateProfilesCleanSchema;\nstatic STEPS: [&dyn MigrationStep; 3] = [&NULL_VALUE, &SCRIPT_NEWTYPE, &CLEAN_SCHEMA];\n\npub struct ProfilesMigrator;\n\nimpl ModuleMigrator for ProfilesMigrator {\n    fn module(&self) -> &'static str {\n        \"profiles\"\n    }\n\n    fn detect_baseline(&self, ctx: &Ctx) -> anyhow::Result<u64> {\n        let profiles_path = ctx.profiles_path();\n        if !profiles_path.exists() {\n            return Ok(current_revision());\n        }\n\n        let raw = std::fs::read_to_string(&profiles_path)?;\n        let profiles: Mapping = serde_yaml::from_str(&raw)\n            .map_err(|e| anyhow::anyhow!(\"failed to parse profiles: {e}\"))?;\n        if is_clean_schema(&profiles) {\n            return Ok(current_revision());\n        }\n        Ok(0)\n    }\n\n    fn steps(&self) -> &'static [&'static dyn MigrationStep] {\n        &STEPS\n    }\n}\n\n#[derive(Debug, Clone, Copy)]\npub struct MigrateProfilesNullValue;\n\nimpl MigrationStep for MigrateProfilesNullValue {\n    fn id(&self) -> &'static str {\n        \"profiles/null_value\"\n    }","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/migration/modules/profiles.rs#L16-L52","documentation":"Raised by the profiles migration module's `detect_baseline` when the profiles YAML file exists but cannot be deserialized into a serde_yaml Mapping. This function inspects the current schema to decide the starting revision for the migration; if the file is unparseable, baseline detection aborts with this error. The raw serde_yaml diagnostic is embedded in the message.","triggerScenarios":"Running migration baseline detection when `profiles_path()` exists but its content is invalid YAML or its root node is not a mapping (e.g. a list or scalar document).","commonSituations":"Manually edited profiles.yaml with a syntax slip; file truncated by disk-full or crash; a subscription importer wrote malformed YAML; empty file left behind by a failed earlier run.","solutions":["Fix the YAML syntax error in the profiles file at the line/column given in the embedded serde_yaml message.","Back up profiles.yaml, then validate it with a standalone YAML linter/parser before restoring.","If unrecoverable, move the file aside (rename to profiles.yaml.bak) so detection treats it as absent and the app regenerates a clean schema.","Verify the root of the document is a mapping (key: value pairs), not a bare sequence or scalar."],"exampleFix":"// before (profiles.yaml truncated by crash)\nitems:\n  - uid: abc\n    name: Profile\n    type: remote\n    url: \"https://example  // unterminated quote\n// after\nitems:\n  - uid: abc\n    name: Profile\n    type: remote\n    url: \"https://example.com/prof.yaml\"","handlingStrategy":"validation","validationCode":"fn profiles_parsable(raw: &str) -> bool {\n    serde_yaml::from_str::<serde_yaml::Mapping>(raw).is_ok()\n}\n// before detect_baseline: let ok = std::fs::read_to_string(&path).map(|r| profiles_parsable(&r)).unwrap_or(false);","typeGuard":"fn root_is_mapping(raw: &str) -> bool {\n    serde_yaml::from_str::<serde_yaml::Value>(raw)\n        .map(|v| v.is_mapping())\n        .unwrap_or(false)\n}","tryCatchPattern":"let profiles: Mapping = match serde_yaml::from_str(&raw) {\n    Ok(m) => m,\n    Err(e) => {\n        eprintln!(\"profiles.yaml unparseable, treating baseline as absent: {e}\");\n        return Ok(0); // fall back to revision 0\n    }\n};","preventionTips":["Validate profiles.yaml with a YAML parser after any manual edit.","Use atomic writes when the app saves profiles so crashes never leave truncated files.","Keep periodic backups of profiles.yaml before upgrading the app.","Check for empty files: an empty file parses as null, not a Mapping."],"tags":["yaml","profiles","migration","parse-error","rust"],"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"}