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
- 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)
- Check DSL helper arity/types against the docs and sanitize inputs (e.g. to_string before to_number)
- Give extractors fallbacks or gate dependent requests with matchers so variables always exist before use
- 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
- Guarantee producer requests matched before consumers reference their extractor outputs
- Name generator payloads exactly as referenced in markers
- Use -v to dump the data map when reproducing
- Give optional values defaults so identifiers never evaluate undefined
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
- failed to compile expression %q: %w
- unresolved variables found: %s
- no records found
- unresolved DSL placeholders must be inside string literals
- unresolved DSL placeholder %q is not inside a string literal
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/cb26cf316007695d.
Report an issue: GitHub.