libnyanpasu/clash-nyanpasu · error

clean-schema output rejected by domain model: {e}

Error message

clean-schema output rejected by domain model: {e}

What it means

After transforming the legacy document into the clean schema, run_clean_schema round-trips the migrated mapping through the typed domain model nyanpasu_config::profile::Profiles. If the deserializer rejects the migrated value (unknown/invalid fields, malformed items, duplicate uids enforced by R13), this error is thrown. It signals the migration transform itself produced an invalid document, so nothing is written.

Source

Thrown at backend/tauri/src/core/migration/modules/profiles.rs:256

    let raw = std::fs::read_to_string(&path)?;
    let doc: Mapping =
        serde_yaml::from_str(&raw).map_err(|e| anyhow::anyhow!("failed to parse profiles: {e}"))?;
    if is_clean_schema(&doc) {
        return Ok(());
    }

    // R15: backup first, then transform (D3: mandatory .bak)
    let bak = path.with_extension("yaml.bak");
    crate::core::migration::fs::atomic_write(&bak, raw.as_bytes())?;

    let migrated = migrate_clean_schema(doc)?;

    // Typed round-trip: the only accepted output is a document the new domain
    // model can load AND validate (design §14.4). Duplicate uids are rejected
    // here by the items deserializer (R13).
    let profiles: nyanpasu_config::profile::Profiles =
        serde_yaml::from_value(Value::Mapping(migrated))
            .map_err(|e| anyhow::anyhow!("clean-schema output rejected by domain model: {e}"))?;
    profiles
        .validate()
        .map_err(|errors| anyhow::anyhow!("clean-schema output failed validation: {errors:?}"))?;

    let body = serde_yaml::to_string(&profiles)
        .map_err(|e| anyhow::anyhow!("failed to serialize migrated profiles: {e}"))?;
    let content = format!("# Profiles Config for Clash Nyanpasu\n\n{body}");
    crate::core::migration::fs::atomic_write(&path, content.as_bytes())?;
    Ok(())
}

fn rollback_clean_schema(ctx: &mut Ctx) -> anyhow::Result<()> {
    let path = ctx.profiles_path();
    let bak = path.with_extension("yaml.bak");
    if !bak.exists() {
        eprintln!("profiles.yaml.bak not found, nothing to roll back");
        return Ok(());
    }

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Inspect {e} to find the offending field/item, then fix the corresponding entry in the source profiles.yaml (e.g. deduplicate or assign unique uids, fill missing required fields) and re-run migration.
  2. Check whether the file was already partially migrated; restore the .yaml.bak and retry on the pristine legacy data.
  3. Verify the nyanpasu-config domain model version matches the migration code — version skew can make valid legacy output invalid.
  4. If it reproduces on legitimate data, report it as a migration-transform bug: the transform should never emit a document the domain model rejects.

Example fix

// before
let profiles: Profiles = serde_yaml::from_value(Value::Mapping(migrated))
    .map_err(|e| anyhow::anyhow!("clean-schema output rejected by domain model: {e}"))?;
// after
let profiles: Profiles = serde_yaml::from_value(Value::Mapping(migrated))
    .with_context(|| format!("clean-schema output rejected by domain model for {}: duplicate uid or invalid item", path.display()))?;
Defensive patterns

Strategy: validation

Validate before calling

fn migrated_output_loads(migrated: &serde_yaml::Mapping) -> Result<(), String> {
    let v = serde_yaml::Value::Mapping(migrated.clone());
    match serde_yaml::from_value::<nyanpasu_config::profile::Profiles>(v) {
        Ok(_) => Ok(()),
        Err(e) => Err(format!("domain model round-trip failed: {e}")),
    }
}

Type guard

fn loads_into_domain_model(migrated: serde_yaml::Mapping) -> bool {
    serde_yaml::from_value::<nyanpasu_config::profile::Profiles>(Value::Mapping(migrated)).is_ok()
}

Try / catch

let profiles: Profiles = match serde_yaml::from_value(Value::Mapping(migrated)) {
    Ok(p) => p,
    Err(e) => {
        eprintln!("migration transform bug: output rejected by domain model: {e}");
        eprintln!("restore profiles.yaml.bak; report duplicate-uid/invalid-item data");
        return Err(e.into());
    }
};

Prevention

When it happens

Trigger: The migrated Mapping contains a profiles document the domain model cannot deserialize: duplicate item uids, items with missing/invalid type or url fields, wrong data types after transform (e.g. string where u32 expected), or legacy fields that map to none of the domain variants.

Common situations: Legacy profiles with unusual or malformed entries (empty uid, duplicate uids from copy-pasted profile blocks, exotic item types) surviving the transform; a bug in the migration transform leaving required fields null; version skew where the domain model gained new constraints the legacy data violates.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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