projectdiscovery/nuclei · error

failed to evaluate expression %q: %w

Error message

failed to evaluate expression %q: %w

What it means

Runtime error from expressions.Evaluate (pkg/protocols/common/expressions/expressions.go:71). The expression compiled fine (govaluate.NewEvaluableExpressionWithFunctions succeeded) but compiled.Evaluate(base) failed — typically because a referenced variable is missing from the base data map or a helper function errored at runtime (e.g. bad argument type). The error wraps the govaluate failure and names the original expression.

Source

Thrown at pkg/protocols/common/expressions/expressions.go:71

	// - simple: containing base values keys (variables)
	// - complex: containing helper functions [ + variables]
	// literals like {{2+2}} are not considered expressions
	for _, expression := range expressions {
		originalExpression := expression
		// data has already had simple placeholders replaced; keep the same
		// marker shape for output replacement, but never compile this string.
		replacedExpression := replacer.Replace(expression, base)
		expression = replaceStringPlaceholders(expression, base)

		// turns expressions (either helper functions+base values or base values)
		compiled, err := govaluate.NewEvaluableExpressionWithFunctions(expression, dsl.HelperFunctions)
		if err != nil {
			return data, fmt.Errorf("failed to compile expression %q: %w", originalExpression, err)
		}

		result, err := compiled.Evaluate(base)
		if err != nil {
			return data, fmt.Errorf("failed to evaluate expression %q: %w", originalExpression, err)
		}

		replacement := result
		// Preserve unresolved markers only when a helper call would otherwise
		// hide them from downstream validation. Plain expressions such as
		// comparisons should evaluate normally.
		if markers := unresolvedVarMarkers(compiled.Vars(), base); markers != "" {
			usesFunctions := false
			for _, token := range compiled.Tokens() {
				if token.Kind == govaluate.FUNCTION {
					usesFunctions = true
					break
				}
			}
			if usesFunctions && ContainsUnresolvedVariables(fmt.Sprint(result)) == nil {
				replacement = markers
			}
		}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Verify every identifier in the expression is present in the data map at evaluation time (generator payload names, extractor names with internal:true, or built-ins like BaseURL)
  2. Check DSL helper arity/types against the docs and sanitize inputs (e.g. to_string before to_number)
  3. Give extractors fallbacks or gate dependent requests with matchers so variables always exist before use
  4. Reproduce with -v and print the base map to see which key is missing

Example fix

# before
- raw:
    - 'X-Token: {{token}}'
  # token never extracted when first request fails
# after
matchers:
  - type: word
    words:
      - 'session'
    internal: true
# (ensure the producing request matched, so {{token}} exists downstream)
Defensive patterns

Strategy: try-catch

Validate before calling

// before evaluating, confirm every identifier the expression uses is present
for _, v := range compiled.Vars() {
	if _, ok := data[v]; !ok {
		return fmt.Errorf("variable %q missing; skip or provide default before evaluation", v)
	}
}

Type guard

func allVarsPresent(expr string, data map[string]interface{}) bool {
	c, err := govaluate.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions)
	if err != nil { return false }
	for _, v := range c.Vars() { if _, ok := data[v]; !ok { return false } }
	return true
}

Try / catch

out, err := expressions.Evaluate(tplText, data)
if err != nil && strings.Contains(err.Error(), "failed to evaluate expression") {
	// missing runtime variable: skip request, or substitute defaults and retry once
}

Prevention

When it happens

Trigger: '{{randstr(1)}}' with wrong arg type, '{{undefined_var}} == 1' where undefined_var is absent from data (this path fires when it compiled as an identifier but no value exists at eval), or a DSL helper whose runtime input is malformed (e.g. to_number('abc')).

Common situations: Flow/fuzz templates referencing extractor outputs that a skipped request never produced; marker variables whose names drift from the generator's payload names (payloads vs payload); helper functions receiving nil after an upstream extraction failure.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/cb26cf316007695d. Report an issue: GitHub.