libnyanpasu/clash-nyanpasu · error

clean-schema output failed validation: {errors:?}

Error message

clean-schema output failed validation: {errors:?}

What it means

After successful deserialization into the domain model, run_clean_schema calls Profiles::validate() to enforce cross-field invariants (design §14.4). If validate() returns errors, the migration aborts with 'clean-schema output failed validation: {errors:?}' and the original file is left untouched (the .bak may already have been written).

Source

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

    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(());
    }
    let raw = std::fs::read(&bak)?;
    crate::core::migration::fs::atomic_write(&path, &raw)
}

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Read the {errors:?} list to identify which invariants failed, and correct the corresponding entries in the source profiles.yaml before re-running migration.
  2. Restore from profiles.yaml.bak and retry migration on pristine data to rule out a previously corrupted half-migration.
  3. If validation fails on reasonable legacy data, treat it as a bug in the migration transform or in validate() and report with the errors list.
  4. Add a pre-check running the same validate() on a dry-run migrated copy to surface issues before committing.

Example fix

// before
profiles.validate()
    .map_err(|errors| anyhow::anyhow!("clean-schema output failed validation: {errors:?}"))?;
// after
profiles.validate()
    .with_context(|| format!("clean-schema validation failed for {} — restore .yaml.bak and fix source data", path.display()))?;
Defensive patterns

Strategy: validation

Validate before calling

if let Err(errors) = profiles.validate() {
    return Err(anyhow::anyhow!("pre-commit validation failed: {errors:?}"));
} // run this on the in-memory Profiles before any serialization/write

Type guard

fn is_valid_profiles(p: &nyanpasu_config::profile::Profiles) -> bool {
    p.validate().is_ok()
}

Try / catch

if let Err(errors) = profiles.validate() {
    eprintln!("clean-schema output failed validation: {errors:?}");
    eprintln!("profiles.yaml left untouched; restore .yaml.bak if needed");
    return Err(anyhow::anyhow!("validation failed: {errors:?}"));
}

Prevention

When it happens

Trigger: The migrated document deserializes fine but violates domain invariants checked by Profiles::validate() — e.g. structurally valid items with semantically invalid combinations, dangling references, or constraint violations not expressible in serde.

Common situations: Legacy data that serde accepts but the new model's semantic rules reject (e.g. duplicate references after transform, ordering/current-pointer inconsistencies); a migration-transform bug producing semantically inconsistent output.

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/fec97d5d5d9a41e0. Report an issue: GitHub.