libnyanpasu/clash-nyanpasu · warning
filter `merge` target item is not a mapping, item kept
Error message
filter `merge` target item is not a mapping, item kept
What it means
When a filter's `merge` action applies to an item, the item must be a mapping; if it is a scalar or array the merge cannot proceed. Unlike the legacy implementation (which panicked via as_mapping_mut().unwrap()), this executor keeps the item and logs a warning instead.
Source
Thrown at backend/nyanpasu-config/src/runtime/executor/overlay.rs:235
return item;
}
match &action {
FilterAction::Expr(expr) => match runner.eval_item_expr(expr, &item) {
Ok(next) => next,
Err(error) => {
logs.push(StepLogEntry::warn(format!(
"filter `expr` failed, item kept: {error}"
)));
item
}
},
FilterAction::Override(replacement) => (*replacement).clone(),
FilterAction::Merge(merge) => {
// Legacy panics on non-mapping items (merge.rs:163
// `as_mapping_mut().unwrap()`); never-fail keeps
// the item instead (spec §13 #15).
if item.as_object_arc().is_none() {
logs.push(StepLogEntry::warn(
"filter `merge` target item is not a mapping, item kept",
));
return item;
}
deep_merge_value(Some(&item), merge)
}
FilterAction::Remove(paths) => remove_from_item(item, paths, logs),
}
})
.collect()
}
_ => {
logs.push(StepLogEntry::warn("invalid filter value, skipped"));
items
}
}
}
View on GitHub (pinned to f7dbce2997)
Solutions
- Restrict the `when` predicate so it only matches mapping items (e.g. check item.type or another object-only field)
- Change the action from `merge` to `override` if replacing the item wholesale is acceptable
- Convert sequence items into mappings before filtering
- Ignore the warning if keeping unmatched non-mapping items is intended
Example fix
// before
when: "true"
merge: { extra: 1 }
// after
when: "item.name != null"
merge: { extra: 1 } Defensive patterns
Strategy: validation
Validate before calling
// in the `when` predicate, restrict to mapping items: // when: "item.name != null" let matched: Vec<_> = items.iter().filter(|i| i.as_object_arc().is_some()).collect(); assert!(!matched.is_empty(), "merge action requires mapping items");
Type guard
fn item_is_mapping(v: &ConfigValue) -> bool { v.as_object_arc().is_some() } Prevention
- Write `when` predicates that only match object items for merge actions
- Avoid mixing scalars and objects in lists targeted by merge filters
- Keep step logging enabled to notice kept-but-unmerged items
When it happens
Trigger: A `when` predicate matches a non-mapping item in the filtered sequence and the action is `merge`.
Common situations: Filtering lists that mix scalars and objects (e.g. rules as plain strings) with a merge action intended for object items.
Related errors
- remove path `{dotted}` on non-mapping item, skipped
- failed to transform to yaml mapping "{}"
- filter expr failed, item removed: {error}
- filter `when` failed, treated as false: {error}
- filter `expr` failed, item kept: {error}
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/1aa5f4c7defa800b.
Report an issue: GitHub.