projectdiscovery/nuclei · error
unresolved DSL placeholders must be inside string literals
Error message
unresolved DSL placeholders must be inside string literals
What it means
Runtime resolution error from resolveDSLStringMarkers (pkg/operators/matchers/dsl_string_markers.go:45). When a DSL matcher expression still contains unresolved {{...}} markers after compile-time variable substitution, nuclei attempts to substitute them only inside string literals of the expression. If findDSLStringMarkers returns zero markers — the expression has unresolved markers but none resided in string literals — this error aborts the matcher with that message.
Source
Thrown at pkg/operators/matchers/dsl_string_markers.go:45
}
type stringLiteralSpan struct {
start int
end int
quote byte
}
func resolveDSLStringMarkers(expression string, data map[string]interface{}) (string, error) {
// Resolve only marker spans already present in the compiled DSL source.
// Values are escaped for the surrounding string literal before recompilation.
stringSpans := findStringLiteralSpans(expression)
markers, err := findDSLStringMarkers(expression, data, stringSpans)
if err != nil {
return "", err
}
if len(markers) == 0 {
return "", fmt.Errorf("unresolved DSL placeholders must be inside string literals")
}
sort.Slice(markers, func(i, j int) bool {
return markers[i].start > markers[j].start
})
resolved := expression
for _, marker := range markers {
result, err := render.Render(render.Input{
Text: "{{" + marker.expr + "}}",
Values: data,
})
if err != nil {
return "", err
}
replacement := expressions.EscapeStringValue(result.Text, marker.quote)
resolved = resolved[:marker.start] + replacement + resolved[marker.end:]View on GitHub (pinned to 265b3a3dec)
Solutions
- Quote the placeholder so it is a string literal: `"'{{payload}}' == '1'"` style, letting the resolver substitute inside quotes
- Fix the variable name so the marker binds at compile time and disappears entirely
- Precompute the value into a named variable (internal:true extractor + {{var}}) instead of inlining a raw marker in the DSL expression
- Re-run with -v to see the exact expression after partial substitution and confirm quoting
Example fix
# before
dsl:
- '{{myvar}} == "admin"'
# after
dsl:
- "'{{myvar}}' == 'admin'" Defensive patterns
Strategy: validation
Validate before calling
// lint: any {{...}} in a dsl matcher must sit between quotes
var bareMarker = regexp.MustCompile(`(^|[^"'])\{\{[^{}]+\}\}($|[^"'])`)
if bareMarker.MatchString(dslExpr) {
return fmt.Errorf("dsl %q contains an unquoted placeholder", dslExpr)
} Type guard
func dslMarkersQuoted(expr string) bool { return !bareMarkerRE.MatchString(expr) } Try / catch
// errors surface at match time; log and drop to no-match, then fix template:
if err := m.Match(data); err != nil && strings.Contains(err.Error(), "unresolved DSL placeholders") {
gologger.Warn().Msgf("template bug in %s: quote {{...}} inside dsl", tplID)
} Prevention
- Always quote placeholders inside DSL strings: "'{{var}}'"
- Prefer bound variables over surviving markers in expressions
- Test fuzz/payload templates against a local echo server before shipping
When it happens
Trigger: A DSL matcher like `dsl: ["{{payload}} == '1'"]` where `{{payload}}` sits outside quotes, and `payload` is not a known govaluate variable/base value at evaluation time, so the raw marker survives to this stage; the marker scan then finds no in-literal candidates and len(markers)==0 triggers the error.
Common situations: Fuzzing/payload templates where generator variables are referenced unquoted inside DSL expressions; marker typos ({{Paylaod}}) that never bind; referencing dynamic extractor names before they are defined; expressions mixing govaluate identifiers with template markers incorrectly.
Related errors
- unresolved DSL placeholder %q is not inside a string literal
- no records found
- failed to compile expression %q: %w
- failed to evaluate expression %q: %w
- payload concurrency must be at least 1
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/2ec1dafea522dbfe.
Report an issue: GitHub.