usememos/memos · error

logical NOT expects one argument

Error message

logical NOT expects one argument

What it means

Returned by buildCallCondition for the "!_" (logical NOT) function when the call does not have exactly 1 argument. Unary ! always carries one arg in normal CEL, so this is an internal/programmatic-AST invariant failure rather than a typical user mistake.

Source

Thrown at internal/filter/parser.go:86

		if len(call.Args) != 2 {
			return nil, errors.New("logical OR expects two arguments")
		}
		left, err := buildCondition(call.Args[0], pc)
		if err != nil {
			return nil, err
		}
		right, err := buildCondition(call.Args[1], pc)
		if err != nil {
			return nil, err
		}
		return &LogicalCondition{
			Operator: LogicalOr,
			Left:     left,
			Right:    right,
		}, nil
	case "!_":
		if len(call.Args) != 1 {
			return nil, errors.New("logical NOT expects one argument")
		}
		child, err := buildCondition(call.Args[0], pc)
		if err != nil {
			return nil, err
		}
		return &NotCondition{Expr: child}, nil
	case "_==_", "_!=_", "_<_", "_>_", "_<=_", "_>=_":
		return buildComparisonCondition(call, pc)
	case "@in":
		return buildInCondition(call, pc)
	case "contains":
		return buildTextMatchCondition(call, pc.schema, TextMatchContains)
	case "startsWith":
		return buildTextMatchCondition(call, pc.schema, TextMatchPrefix)
	case "endsWith":
		return buildTextMatchCondition(call, pc.schema, TextMatchSuffix)
	case "matches":
		return buildMatchesCondition(call, pc.schema)

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Use plain unary negation in the filter text: !pinned.
  2. When building ASTs, emit !_ with exactly one argument.
  3. Treat occurrence from a normal filter string as an engine bug and report it.

Example fix

# before (synthetic AST misuse)

# after (plain filter)
!pinned
Defensive patterns

Strategy: validation

Validate before calling

// Go — emit plain unary NOT when generating
func not(e string) string { return fmt.Sprintf("!(%s)", e) }

Try / catch

if err != nil && strings.Contains(err.Error(), "logical NOT expects one argument") {
  return errors.Wrap(err, "internal filter AST inconsistency; report with the filter text")
}

Prevention

When it happens

Trigger: An Expr_Call tagged !_ with arity != 1 — essentially only possible with hand-built ASTs or a malformed macro expansion, not from parsing a user string.

Common situations: Programmatic filter construction; testing the parser with synthetic ASTs.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/1fc821e947042178. Report an issue: GitHub.