projectdiscovery/nuclei · error
failed to compile expression %q: %w
Error message
failed to compile expression %q: %w
What it means
Runtime error from expressions.Evaluate (pkg/protocols/common/expressions/expressions.go:66). After simple placeholders are replaced, each remaining marker is treated as a govaluate expression and compiled with dsl.HelperFunctions. A syntactically invalid expression returns this error wrapping the govaluate failure and echoing the ORIGINAL marker text (originalExpression), so callers can pinpoint the bad template fragment.
Source
Thrown at pkg/protocols/common/expressions/expressions.go:66
// replace simple placeholders (key => value) MarkerOpen + key + MarkerClose and General + key + General to value
data = replacer.Replace(data, base)
// expressions can be:
// - 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
}View on GitHub (pinned to 265b3a3dec)
Solutions
- Fix the marker syntax: balanced braces, valid operators, correct DSL helper arity (check `nuclei -dast` docs / dsl function list via `-h` or dsl.FunctionNames)
- Pre-test expressions: put them in a `type: dsl` matcher/extractor and run `nuclei -validate -t template.yaml`
- Keep complex logic in the DSL section rather than inline markers where possible
- Quote string operands: "'{{var}}' + 'x'" rather than raw concatenation
Example fix
# before
- raw:
- 'GET /{{path++}} HTTP/1.1'
# after
- raw:
- "GET /{{path}} HTTP/1.1" Defensive patterns
Strategy: try-catch
Validate before calling
import gvl "github.com/projectdiscovery/govaluate"
for _, expr := range expressions.FindExpressions(payloadOrRaw, "{{", "}}", data) {
if _, err := gvl.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions); err != nil {
return fmt.Errorf("marker %q will fail to compile: %w", expr, err)
}
} Type guard
func markerExprCompiles(expr string) bool { _, err := govaluate.NewEvaluableExpressionWithFunctions(expr, dsl.HelperFunctions); return err == nil } Try / catch
out, err := expressions.Evaluate(template, data)
if err != nil && strings.Contains(err.Error(), "failed to compile expression") {
// log original marker text (it is quoted in the error) and skip that request gracefully
} Prevention
- Keep inline markers to simple variables; put logic in dsl: sections
- Check DSL helper names/arity against the shipped version before upgrading
- Validate templates with -validate and exercise fuzz templates against a local echo server
When it happens
Trigger: A {{...}} marker that is neither a simple variable nor a valid expression — e.g. '{{BaseURL} }' (bad spacing), '{{payload++}}' with stray operators, or a helper call with wrong arity like '{{md5()}}' (md5 expects 1 arg) — encountered while rendering raw requests, payloads, or flow steps.
Common situations: Fuzzing templates building arithmetic/string expressions from generator values; hand-authored markers with typos; DSL function signature drift after nuclei upgrades (renamed/arity-changed helpers); copy-paste of Go code into markers.
Related errors
- failed to evaluate expression %q: %w
- no records found
- unresolved DSL placeholders must be inside string literals
- unresolved DSL placeholder %q is not inside a string literal
- payload concurrency must be at least 1
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/d51dd37d8974f235.
Report an issue: GitHub.