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

  1. Ensure the `split_legacy_config` migration runs (and succeeds) before this repair step in the migration sequence.
  2. If this is a fresh install with intentionally no config, skip the repair step rather than treating absent files as an error.
  3. 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

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


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/d34eb7fabc8c94bc. Report an issue: GitHub.