projectdiscovery/nuclei · error
unresolved variables found: %s
Error message
unresolved variables found: %s
What it means
Raised by the unresolved-variable checker in pkg/protocols/common/expressions (variables.go:41). It scans each input string for {{...}} markers; matches that are pure arithmetic expressions or literal-only govaluate expressions (resolvable by the DSL engine) are skipped, and every remaining {{name}} is collected. If any remain, it returns 'unresolved variables found: a,b' so the caller knows which markers would be sent literally.
Source
Thrown at pkg/protocols/common/expressions/variables.go:41
return nil
}
var unresolvedVariables []string
for _, match := range matches {
if len(match) < 2 {
continue
}
// Skip if the match is an expression
if numericalExpressionRegex.MatchString(match[1]) {
continue
}
// or if it contains only literals (can be solved from expression engine)
if hasLiteralsOnly(match[1]) {
continue
}
unresolvedVariables = append(unresolvedVariables, match[1])
}
if len(unresolvedVariables) > 0 {
return errors.New("unresolved variables found: " + strings.Join(unresolvedVariables, ","))
}
}
return nil
}
// ContainsVariablesWithNames returns an error with variable names if the passed
// input contains unresolved {{<pattern-here>}} variables within the provided list
func ContainsVariablesWithNames(names map[string]interface{}, items ...string) error {
for _, data := range items {
matches := unresolvedVariablesRegex.FindAllStringSubmatch(data, -1)
if len(matches) == 0 {
return nil
}
var unresolvedVariables []string
for _, match := range matches {
if len(match) < 2 {
continueView on GitHub (pinned to 265b3a3dec)
Solutions
- Define the value in the template's variables block, payloads, or a preceding flow/extract step
- Fix the marker name so it exactly matches the payload/variable key
- For literal braces that are not placeholders, keep the content literal-only or arithmetic so the checker can resolve or skip it
Example fix
# before
http:
- raw:
- 'GET /api/{{version}}/user HTTP/1.1'
# after
http:
- raw:
- 'GET /api/{{version}}/user HTTP/1.1'
variables:
version: 'v2' Defensive patterns
Strategy: validation
Validate before calling
if err := expressions.ContainsUnresolvedVariables(rawRequest, headers...); err != nil {
return fmt.Errorf("fix template before run: %w", err)
} Type guard
func hasUnresolvedVariables(err error) bool { return strings.HasPrefix(err.Error(), "unresolved variables found:") } Try / catch
err := expressions.ContainsUnresolvedVariables(items...)
if err != nil { names := strings.Split(strings.TrimPrefix(err.Error(), "unresolved variables found: "), ",") /* map names back to missing definitions */ } Prevention
- Run the unresolved-variable check in template lint CI
- Name payloads and markers identically (single source of truth)
- Keep literals inside DSL expressions so the engine can resolve them
When it happens
Trigger: A raw HTTP request body containing {{username}} with no payload, variables or flow value defining 'username'; a path like /api/{{version}}/user where version is never set.
Common situations: Template refactor removes a variables block but leaves the marker; marker name typo relative to the payload key ({{usr}} vs payload 'user'); copying a raw request from Burp that contains templated-looking braces.
Related errors
- unresolved variables with values found: %s
- invalid dns type
- failed to evaluate expression %q: %w
- validation failed for these fields
- payload concurrency must be at least 1
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/a98d9a197118f69f.
Report an issue: GitHub.