libnyanpasu/clash-nyanpasu · error
failed to parse config: {e}
Error message
failed to parse config: {e} What it means
Thrown by the app_config migration module's `detect_baseline`, which reads the Nyanpasu config YAML and parses it into a `serde_yaml::Mapping` to decide whether migrations are needed. If the file's content is not valid YAML, `serde_yaml::from_str` fails and the error is wrapped as "failed to parse config: {e}" with serde_yaml's message appended. The file exists, but its content is unreadable as YAML.
Source
Thrown at backend/tauri/src/core/migration/modules/app_config.rs:40
const NETWORK_STATISTIC_WIDGET_KEY: &str = "network_statistic_widget";
pub struct AppConfigMigrator;
impl ModuleMigrator for AppConfigMigrator {
fn module(&self) -> &'static str {
"app_config"
}
fn detect_baseline(&self, ctx: &Ctx) -> anyhow::Result<u64> {
let config_path = ctx.nyanpasu_config_path();
if !config_path.exists() {
return Ok(current_revision());
}
let raw = std::fs::read_to_string(&config_path)?;
let config: Mapping = serde_yaml::from_str(&raw)
.map_err(|e| anyhow::anyhow!("failed to parse config: {e}"))?;
if needs_language_option_migration(&config)
|| needs_theme_setting_migration(&config)
|| needs_network_statistic_widget_migration(&config)
|| needs_language_case_migration(&config)
{
Ok(0)
} else {
Ok(current_revision())
}
}
fn steps(&self) -> &'static [&'static dyn MigrationStep] {
&STEPS
}
}
#[derive(Debug, Clone, Copy)]
pub struct MigrateLanguageOption;View on GitHub (pinned to f7dbce2997)
Solutions
- Open the config file at the logged path and fix the YAML syntax error reported after the colon in the message
- Restore the config from backup or delete/rename the corrupt file so the app regenerates defaults (note: settings will reset)
- Validate the YAML with a linter (e.g. `yamltidy`/online parser) before saving hand edits
- Ensure writes go through crash-safe paths like `atomic_write` instead of direct truncating writes
Defensive patterns
Strategy: try-catch
Validate before calling
fn config_yaml_is_valid(path: &std::path::Path) -> bool {
std::fs::read_to_string(path)
.ok()
.map(|raw| serde_yaml::from_str::<serde_yaml::Mapping>(&raw).is_ok())
.unwrap_or(false)
} Try / catch
match detect_baseline(&ctx) {
Ok(rev) => rev,
Err(e) if e.to_string().contains("failed to parse config") => {
log::warn!("config unreadable, treating as unmigrated default: {e:#}");
backup_and_reset_config(&ctx);
current_revision()
}
Err(e) => return Err(e),
} Prevention
- Only write the config through `atomic_write` so crashes cannot truncate it
- Validate YAML with a linter before saving hand edits
- Keep timestamped backups of the config before upgrades/migrations
- Ensure files are saved as UTF-8 and never overwritten with JSON or other formats
When it happens
Trigger: `detect_baseline` reads `ctx`'s nyanpasu config path, the file exists, but `serde_yaml::from_str::<Mapping>` fails — e.g. corrupt file, empty/garbage content, duplicate keys rejected by the parser, or the file was hand-edited with YAML syntax errors (bad indentation, tabs, unbalanced quotes).
Common situations: Crash or power loss mid-write leaving a truncated config; manual editing of the YAML config; a tool wrote JSON or another format into the YAML file; encoding issues from non-UTF-8 bytes on disk.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- legacy verge snapshot must serialize as a mapping
- cannot repair typed clash config before split_legacy_config
- unrecognized typed config migration state: existing {} is ne
- Invalid theme color: {}
- file not found "{}"
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/b63b16dcd65e3df0.
Report an issue: GitHub.