libnyanpasu/clash-nyanpasu · error
cannot repair typed clash config before split_legacy_config
Error message
cannot repair typed clash config before split_legacy_config has completed
What it means
The typed-config migration module inspects on-disk state via `typed_file_state` before repairing the typed clash config. If no migration artifacts exist at all (`TypedFileState::None`), the repair step cannot run because `split_legacy_config` — the step that produces the typed files — has not completed. It fails deliberately to enforce migration ordering.
Source
Thrown at backend/tauri/src/core/migration/modules/typed_config.rs:118
}
fn revision(&self) -> u64 {
2
}
fn introduced_in(&self) -> &'static Version {
&VERSION_2_0_0
}
fn name(&self) -> &'static str {
"RepairClashConfigPath"
}
fn run(&self, ctx: &mut Ctx) -> anyhow::Result<()> {
match typed_file_state(ctx)? {
TypedFileState::All => return Ok(()),
TypedFileState::None => {
bail!("cannot repair typed clash config before split_legacy_config has completed")
}
TypedFileState::NeedsClashRepair => {}
}
let previous_typed_path = ctx.paths().app_config_dir().join(PREVIOUS_TYPED_CLASH_FILE);
let clash_config = if previous_typed_path.exists() {
read_yaml::<nyanpasu_config::clash::config::ClashConfig>(&previous_typed_path)
.context("failed to read previous typed clash config")?
} else {
let legacy = read_legacy_verge(&ctx.nyanpasu_config_path())?;
let legacy_clash = read_legacy_clash_inputs(ctx)?;
let (_, _, clash_config) = typed_config_from_legacy_parts(&legacy, &legacy_clash)?;
clash_config
};
let clash_yaml =
serialize_yaml(&clash_config).context("failed to serialize repaired clash config")?;
crate::core::migration::fs::atomic_write(&ctx.clash_config_path(), clash_yaml.as_bytes())View on GitHub (pinned to f7dbce2997)
Solutions
- Ensure the `split_legacy_config` migration runs (and succeeds) before this repair step in the migration sequence.
- If this is a fresh install with intentionally no config, skip the repair step rather than treating absent files as an error.
- Restore the expected config files from backup so `typed_file_state` returns `All` or `NeedsClashRepair`.
Example fix
// before
migrations.push(typed_config_repair); // runs even on fresh installs
// after
if typed_file_state(&ctx)? != TypedFileState::None {
migrations.push(typed_config_repair);
} Defensive patterns
Strategy: validation
Validate before calling
let clash = paths.app_config_dir().join("clash-config.yaml");
if !clash.exists() && !paths.app_config_dir().join("config.yaml").exists() {
// fresh install: skip repair step
} Try / catch
match migration.run(&mut ctx) {
Err(e) if e.to_string().contains("split_legacy_config has completed") => {
log::warn!("repair step skipped: prerequisites missing; running split first");
split_legacy_config.run(&mut ctx)?;
migration.run(&mut ctx)?;
}
other => other?,
} Prevention
- Keep the full migration chain registered and ordered; never run later repair steps standalone.
- Do not manually delete config files expected by migration steps.
- On fresh installs, short-circuit the repair step when the config dir is empty.
When it happens
Trigger: Running the `run` step of the typed-clash-config repair migration when the app config dir contains neither typed files nor legacy artifacts, i.e. `split_legacy_config` never ran (fresh install or missing prerequisite migration step).
Common situations: Manually deleting the config directory contents while keeping the migration registered; running migrations out of order after editing the migration list; restoring a partial backup that predates the split step.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- unrecognized typed config migration state: existing {} is ne
- partial typed config migration state: existing [{}], missing
- unsupported migration store schema version {}
- Invalid theme color: {}
- legacy mutation may have non-reversible side effects and req
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/d34eb7fabc8c94bc.
Report an issue: GitHub.