crowdsecurity/crowdsec · error

failed to compile node in '%s' : %s

Error message

failed to compile node in '%s' : %s

What it means

During loading of a parser stage file, one of the nodes (a filter or a parse/whitelist stanza) failed to compile its expressions or configuration. Since the node has no name, CrowdSec cannot identify it in the message, so it reports only the stage file where the bad node lives. The stage cannot be loaded and parser startup aborts.

Source

Thrown at pkg/parser/stage.go:141

		if err != nil {
			return nil, fmt.Errorf("failed to check version : %s", err)
		}

		if !ok {
			log.Errorf("%s : %s doesn't satisfy parser format %s, skip", node.Name, node.FormatVersion, constraint.Parser)
			continue
		}

		node.Stage = stageFile.Stage
		// compile the node : grok pattern and expression

		err = node.compile(pctx, ectx)
		if err != nil {
			if node.Name != "" {
				return nil, fmt.Errorf("failed to compile node '%s' in '%s' : %s", node.Name, stageFile.Filename, err)
			}

			return nil, fmt.Errorf("failed to compile node in '%s' : %s", stageFile.Filename, err)
		}
		/* if the stage is empty, the node is empty, it's a trailing entry in users yaml file */
		if node.Stage == "" {
			continue
		}

		for _, data := range node.Data {
			err = exprhelpers.FileInit(pctx.DataFolder, data.DestPath, data.Type)
			if err != nil {
				log.Error(err.Error())
			}

			if data.Type == "regexp" { // cache only makes sense for regexp
				if err = exprhelpers.RegexpCacheInit(data.DestPath, *data); err != nil {
					log.Error(err.Error())
				}
			}
		}

View on GitHub (pinned to 909b515798)

Solutions

  1. Open the stage file named in the message and find the unnamed node; give it a `name:` field so future errors identify it.
  2. Validate every expr expression in that node (filter, statics expressions) against the evt pipeline schema; fix typos/unknown fields.
  3. If the node is truly empty (trailing entry in user yaml), remove it — the code deliberately skips nodes whose Stage is empty.
  4. Run `cscli hubtool` or restart crowdsec after each edit to confirm the stage loads.

Example fix

// before (parsers/s02-enrich/example.yaml, unnamed node with bad expr)
- filter: evt.Parsed.service == 'sshd' and
  ...
// after
- name: example-sshd-node
  filter: evt.Parsed.program == 'sshd'
  ...
Defensive patterns

Strategy: validation

Validate before calling

// before loading stages, lint every node expression
for _, f := range stageFiles {
    nodes := parseNodes(f)
    for i, n := range nodes {
        if n.Name == "" {
            log.Warnf("%s: node %d has no name; give it one for debuggability", f, i)
        }
        if _, err := expr.Compile(n.Filter, exprhelpers.GetExprOptions(map[string]any{"evt": &pipeline.Event{}})...); err != nil {
            return fmt.Errorf("%s: node %q bad filter: %w", f, n.Name, err)
        }
    }
}

Try / catch

if err := LoadStages(cfg); err != nil {
    var se *StageError
    if errors.As(err, &se) { /* stage file se.File, fix node */ }
    log.Fatalf("parser load failed: %v", err)
}

Prevention

When it happens

Trigger: LoadStages -> processStageFile reads a stage YAML file and calls node.compile(pctx, ectx); the node returns a compile error (bad expr filter, invalid runtime field expression) and node.Name is empty (e.g. a node defined as a list entry without a 'name' key or a top-level filter/parse map).

Common situations: A user-edited parser file in /etc/crowdsec/parsers/... where a node is written in short YAML form (list item) so it carries no name, and its `filter` expression has a typo (unknown field, bad operator), or the `expression` in a statics block is invalid.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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