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 {
				continue

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Define the value in the template's variables block, payloads, or a preceding flow/extract step
  2. Fix the marker name so it exactly matches the payload/variable key
  3. 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

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


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