sxyazi/yazi · error

Invalid condition: {expr}

Error message

Invalid condition: {expr}

What it means

`Condition::from_str` parses a boolean condition expression (operators `|`, `&`, `!`, parentheses). After building the parser, it sanity-checks the expression by evaluating with all terms true; if evaluation returns None the syntax is structurally invalid (e.g. dangling operators, unbalanced parens, stray characters) and it bails with the offending expression.

Source

Thrown at yazi-shared/src/condition.rs:69

			// Keep repeated `!` right-associative by making `! >= !` false.
			Equal if matches!((self, other), (Self::Not, Self::Not)) => None,
			ordering => Some(ordering),
		}
	}
}

#[derive(Debug, DeserializeFromStr)]
pub struct Condition {
	ops: Vec<ConditionOp>,
}

impl FromStr for Condition {
	type Err = anyhow::Error;

	fn from_str(expr: &str) -> Result<Self, Self::Err> {
		let cond = Self::build(expr);
		if cond.eval(|_| true).is_none() {
			bail!("Invalid condition: {expr}");
		}

		Ok(cond)
	}
}

impl Condition {
	fn build(expr: &str) -> Self {
		let mut stack: Vec<ConditionOp> = vec![];
		let mut output: Vec<ConditionOp> = vec![];

		let mut chars = expr.chars().peekable();
		while let Some(token) = chars.next() {
			let op = ConditionOp::new(token);
			match op {
				ConditionOp::Or | ConditionOp::And | ConditionOp::Not => {
					while matches!(stack.last(), Some(last) if last >= &op) {
						output.push(stack.pop().unwrap());

View on GitHub (pinned to 5f901b886b)

Solutions

  1. Fix the expression syntax: balanced parentheses and operands around every `|`/`&`/`!`
  2. Verify each non-operator token is a valid term and remove stray characters
  3. Test the expression evaluates as expected before putting it in config

Example fix

-- before (dangling operator)
condition = "mime & "
-- after
condition = "mime & big"
Defensive patterns

Strategy: validation

Validate before calling

local function check_balanced(expr)
  local depth = 0
  for c in expr:gmatch("%(") do depth = depth + 1 end
  for c in expr:gmatch("%)") do depth = depth - 1 end
  assert(depth == 0 and #expr > 0, "unbalanced or empty condition: " .. expr)
end

Type guard

fn valid_condition(expr: &str) -> Option<Condition> { expr.parse::<Condition>().ok() }

Try / catch

let cond = expr.parse::<Condition>()
    .with_context(|| format("bad condition expression: {expr}"))?;

Prevention

When it happens

Trigger: Parsing a condition string containing empty input, unmatched `(`/`)`, operators without operands like `a & & b`, `!` with no term, or invalid characters that produce no evaluable result, e.g. in config fields parsed as Condition via DeserializeFromStr.

Common situations: Hand-edited yazi.toml/rules condition strings with typos; generating conditions programmatically and joining with `&` when a list is empty; forgetting that plain words are terms and symbols are operators.

Related errors


AI-assisted analysis of sxyazi/yazi@5f901b886b (2026-09-02). Data as JSON: /api/errors/a289e46a426ab515. Report an issue: GitHub.