crowdsecurity/crowdsec · error

non-empty filter %q was not compiled

Error message

non-empty filter %q was not compiled

What it means

Node.validate() enforces that any node with a non-empty Filter has already had that expression compiled into RunTimeFilter. If Filter is set but RunTimeFilter is nil, the compile step was skipped or failed silently, so validation rejects the node to prevent runtime evaluation of an uncompiled expression.

Source

Thrown at pkg/parser/node.go:80

		child := Node{NodeConfig: subNodes[i]}
		child.initRuntimeChildrenFromConfig()
		n.LeavesNodes[i] = child
	}
}

func (n *Node) validate(ectx EnricherCtx) error {
	// stage is being set automagically
	if n.Stage == "" {
		return errors.New("stage needs to be an existing stage")
	}

	/* "" behaves like continue */
	if n.OnSuccess != "continue" && n.OnSuccess != "next_stage" && n.OnSuccess != "" {
		return fmt.Errorf("onsuccess %q not continue,next_stage", n.OnSuccess)
	}

	if n.Filter != "" && n.RunTimeFilter == nil {
		return fmt.Errorf("non-empty filter %q was not compiled", n.Filter)
	}

	if n.RuntimeGrok.RunTimeRegexp != nil || n.Grok.TargetField != "" {
		if err := n.Grok.Validate(); err != nil {
			return err
		}
	}

	for idx, static := range n.Statics {
		if err := static.Validate(ectx); err != nil {
			return fmt.Errorf("static %d: %w", idx, err)
		}
	}

	for idx, stash := range n.Stashes {
		if err := stash.Validate(); err != nil {
			return fmt.Errorf("stash %d: %w", idx, err)
		}

View on GitHub (pinned to 909b515798)

Solutions

  1. Ensure node.Compile()/the compilation stage runs before validate(); fix the calling order in the loader.
  2. If constructing nodes in code or tests, explicitly compile the filter expression with exprhelpers options before validating.
  3. If the filter failed to compile earlier, fix the underlying expression error surfaced by the compile step.

Example fix

// before
node := &Node{Filter: "evt.Parsed.x == '1'"}
node.Validate()
// after
node := &Node{Filter: "evt.Parsed.x == '1'"}
if err := node.Compile(pctx); err != nil { return err }
if err := node.Validate(ectx); err != nil { return err }
Defensive patterns

Strategy: type-guard

Validate before calling

if node.Filter != "" && node.RunTimeFilter == nil {
    // compile before validating
    if err := node.Compile(pctx); err != nil { return err }
}

Type guard

func filterCompiled(n *parsers.Node) bool {
    return n.Filter == "" || n.RunTimeFilter != nil
}

Try / catch

if !filterCompiled(node) {
    if err := node.Compile(pctx); err != nil { return err }
}
if err := node.Validate(ectx); err != nil { return err }

Prevention

When it happens

Trigger: validate() sees n.Filter != "" while n.RunTimeFilter == nil — the filter expression was never compiled (e.g. compile step bypassed, or filter present but compilation returned nil on some path).

Common situations: Programmatically constructed nodes (or test harnesses) that set Filter without calling the expression compilation step; config plumbing bugs where compile() wasn't invoked before validate().

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/1c8c65ff4411ff5e. Report an issue: GitHub.