libnyanpasu/clash-nyanpasu · error

failed to transform to yaml mapping "{}"

Error message

failed to transform to yaml mapping "{}"

What it means

read_merge_mapping reads a YAML file and applies merge keys, then requires the document root to be a YAML mapping. If the file parses but its top level is a scalar, a sequence, or empty/null, it throws this error including the file path.

Source

Thrown at backend/tauri/src/utils/help.rs:52

        .with_context(|| format!("failed to read the file \"{}\"", path.display()))?;

    serde_yaml::from_str::<T>(&yaml_str).with_context(|| {
        format!(
            "failed to read the file with yaml format \"{}\"",
            path.display()
        )
    })
}

/// read mapping from yaml fix #165
pub fn read_merge_mapping(path: &PathBuf) -> Result<Mapping> {
    let mut val: Value = read_yaml(path)?;
    val.apply_merge()
        .with_context(|| format!("failed to apply merge \"{}\"", path.display()))?;

    Ok(val
        .as_mapping()
        .ok_or(anyhow!(
            "failed to transform to yaml mapping \"{}\"",
            path.display()
        ))?
        .to_owned())
}

/// save the data to the file
/// can set `prefix` string to add some comments
pub fn save_yaml<T: Serialize, P: AsRef<Path>>(
    path: P,
    data: &T,
    prefix: Option<&str>,
) -> Result<()> {
    let path = path.as_ref();
    let data_str = serde_yaml::to_string(data)?;

    let yaml_str = match prefix {
        Some(prefix) => format!("{prefix}\n\n{data_str}"),

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Ensure the file's top level is a key: value mapping, e.g. `rules: [...]`.
  2. Remove comment-only content and save the file with at least one top-level key.
  3. Validate the YAML root type in a YAML parser before loading.
  4. If the file should be empty, use `{}` as content instead of a zero-byte file.

Example fix

# before (invalid: list root)
- MATCH,DIRECT
# after (valid: mapping root)
rules:
  - MATCH,DIRECT
Defensive patterns

Strategy: validation

Validate before calling

import yaml
cfg = yaml.safe_load(open(merge_path))
assert isinstance(cfg, dict), f'{merge_path} root must be a mapping'

Try / catch

try {
  await loadMergeProfile(path);
} catch (e) {
  if (String(e).includes('failed to transform to yaml mapping')) {
    openEditorAtPath(path); // let the user fix the root type
  } else throw e;
}

Prevention

When it happens

Trigger: Calling read_merge_mapping on a merge/patch YAML whose root is a list, a bare scalar, an empty file (null), or only comments.

Common situations: Users create an empty merge.yaml from a template, paste a rules-only YAML list instead of a mapping, or save a file containing only comment lines.

Related errors


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