{"record":{"id":"000d74640b1be98e","repo":"libnyanpasu/clash-nyanpasu","slug":"unrecognized-typed-config-migration-state-existin","errorCode":null,"errorMessage":"unrecognized typed config migration state: existing {} is neither a valid typed clash config nor a recognized legacy runtime config; restore or remove it before retrying","messagePattern":"unrecognized typed config migration state: existing (.+?) is neither a valid typed clash config nor a recognized legacy runtime config; restore or remove it before retrying","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/core/migration/modules/typed_config.rs","lineNumber":169,"sourceCode":"    Typed,\n    LegacyRuntime,\n    Unrecognized,\n}\n\nfn typed_file_state(ctx: &Ctx) -> anyhow::Result<TypedFileState> {\n    let application_exists = typed_path_exists(&ctx.application_config_path())?;\n    let session_exists = typed_path_exists(&ctx.session_state_path())?;\n    let clash_state = classify_shared_clash_file(ctx)?;\n\n    if !application_exists && !session_exists {\n        return match clash_state {\n            SharedClashFileState::Missing => Ok(TypedFileState::None),\n            SharedClashFileState::LegacyRuntime => Ok(TypedFileState::None),\n            SharedClashFileState::Typed => partial_typed_file_state(\n                vec![\"clash-config.yaml\"],\n                vec![\"application.yaml\", \"session-state.yaml\"],\n            ),\n            SharedClashFileState::Unrecognized => bail!(\n                \"unrecognized typed config migration state: existing {} is neither \\\n                 a valid typed clash config nor a recognized legacy runtime config; restore or \\\n                 remove it before retrying\",\n                ctx.clash_config_path().display()\n            ),\n        };\n    }\n\n    if application_exists && session_exists {\n        match clash_state {\n            SharedClashFileState::Typed => {\n                validate_existing_typed_files(ctx)?;\n                return Ok(TypedFileState::All);\n            }\n            SharedClashFileState::Missing | SharedClashFileState::LegacyRuntime => {\n                validate_existing_application_and_session(ctx)?;\n                return Ok(TypedFileState::NeedsClashRepair);\n            }","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/core/migration/modules/typed_config.rs#L151-L187","documentation":"`typed_file_state` classifies the shared clash config file (valid typed config, legacy runtime config, partial, missing). When the existing file at `ctx.clash_config_path()` parses as neither a valid typed clash config nor a recognized legacy runtime config, the function fails with this guidance message rather than guessing. The `{}` is filled with the full file path.","triggerScenarios":"Calling `typed_file_state` (via `detect_baseline` or `run`) when the clash config file exists but its content/schema is unrecognized — e.g. corrupted YAML, hand-edited file, or a format from an unknown version.","commonSituations":"Manual edits or third-party tools rewriting clash-config.yaml; truncated file from a crash mid-write; config from a much older/newer version with an incompatible schema.","solutions":["Inspect the file reported in the error and restore a known-good version from backup.","Delete or move the unrecognized file so migration can regenerate it (after backing it up).","Check for schema changes between app versions and run the appropriate config conversion first."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let raw = std::fs::read_to_string(ctx.clash_config_path())?;\nlet v: serde_yaml::Value = serde_yaml::from_str(&raw)?; // rejects corrupted files pre-migration\nif v.get(\"mode\").is_none() && v.get(\"proxies\").is_none() {\n    return Err(anyhow::anyhow!(\"clash config schema unrecognized, restore backup\"));\n}","typeGuard":"fn looks_like_typed_or_legacy(v: &serde_yaml::Value) -> bool {\n    v.get(\"mode\").is_some() || v.get(\"proxies\").is_some() || v.get(\"profiles\").is_some()\n}","tryCatchPattern":"match detect_baseline(&mut ctx) {\n    Err(e) if e.to_string().contains(\"unrecognized typed config migration state\") => {\n        let path = ctx.clash_config_path().to_path_buf();\n        std::fs::rename(&path, path.with_extension(\"bak\"))?;\n        retry_migration(&mut ctx)?;\n    }\n    other => other?,\n}","preventionTips":["Validate clash-config.yaml parses and matches a known schema before invoking migration.","Keep backups of config files before app upgrades.","Avoid hand-editing managed config files; use the app's config UI.","Quiesce writes (close the app) before editing or copying config files to avoid truncated files."],"tags":["migration","config","yaml","schema"],"backgroundTag":"schema-validation-failed","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"}