libnyanpasu/clash-nyanpasu · warning

invalid filter: no action

Error message

invalid filter: no action

What it means

apply_filter parsed a valid object filter with a `when` predicate, but none of the recognized action keys (override, merge, remove) were present, so no action can run. It warns and returns the items unfiltered.

Solutions

  1. Add one of the supported action keys: `override` (any value), `merge` (mapping), or `remove` (array of paths)
  2. Fix typos in the action key name
  3. Ensure `remove` is an array, not a string
  4. Cross-check the filter schema in the overlay docs

Example fix

// before
filter:
  when: "item.name == 'A'"
  removes:
    - udp
// after
filter:
  when: "item.name == 'A'"
  remove:
    - udp
Defensive patterns

Strategy: validation

Validate before calling

if let ConfigValue::Object(actions) = &filter {
    let has_action = actions.contains_key("override")
        || matches!(actions.get("merge"), Some(ConfigValue::Object(_)))
        || matches!(actions.get("remove"), Some(ConfigValue::Array(_)));
    assert!(has_action, "filter must define override, merge, or remove");
}

Type guard

fn filter_has_action(f: &ConfigValue) -> bool {
    matches!(f, ConfigValue::Object(a) if a.contains_key("override") || a.contains_key("merge") || a.contains_key("remove"))
}

Prevention

When it happens

Trigger: A filter object has `when` but its action key is misspelled or missing (e.g. `merges`, `del`, `override` holding a non-object value, `remove` not being an array).

Common situations: Typos in action names; `remove` written as a string instead of an array of paths; copy-pasted filter snippets from older schema versions.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at backend/nyanpasu-config/src/runtime/executor/overlay.rs:201

            enum FilterAction<'a> {
                Expr(&'a str),
                Override(&'a ConfigValue),
                Merge(&'a ConfigValue),
                Remove(&'a Arc<[ConfigValue]>),
            }
            let action = if let Some(ConfigValue::String(expr)) = actions.get("expr") {
                FilterAction::Expr(expr.as_ref())
            } else if let Some(replacement) = actions.get("override") {
                FilterAction::Override(replacement)
            } else if let Some(merge) = actions
                .get("merge")
                .filter(|value| value.as_object_arc().is_some())
            {
                FilterAction::Merge(merge)
            } else if let Some(ConfigValue::Array(paths)) = actions.get("remove") {
                FilterAction::Remove(paths)
            } else {
                logs.push(StepLogEntry::warn("invalid filter: no action"));
                return items;
            };
            items
                .into_iter()
                .map(|item| {
                    let hit = match runner.eval_item_predicate(when, &item) {
                        Ok(hit) => hit,
                        Err(error) => {
                            logs.push(StepLogEntry::warn(format!(
                                "filter `when` failed, treated as false: {error}"
                            )));
                            false
                        }
                    };
                    if !hit {
                        return item;
                    }
                    match &action {

View on GitHub (pinned to f7dbce2997)