projectdiscovery/nuclei · error

encountered errors while performing template validation

Error message

encountered errors while performing template validation

What it means

Twin cleanup guard in the same defer: the code panics when os.Remove of the temp file fails. On Windows this is classically antivirus/EDR still holding the file open; elsewhere it is a vanished file or lost permissions on the temp directory. It panics by design so cleanup failures are never swallowed.

Solutions

  1. Add an antivirus exclusion for the TMPDIR nuclei uses (and the nuclei binary)
  2. Give each run a private TMPDIR with permissive cleanup
  3. Re-run the single failing file to confirm the cause; report persistent cases upstream

Example fix

# before: shared temp dir policed by AV
# after
mkdir -p /var/tmp/nuclei-run && TMPDIR=/var/tmp/nuclei-run nuclei -t file.yaml -l files.txt
Defensive patterns

Strategy: try-catch

Try / catch

defer func() {
    if r := recover(); r != nil {
        // temp-file removal panic (often AV lock on Windows): log and continue
        log.Printf("file protocol cleanup panic: %v", r)
    }
}()
err := engine.ExecuteWithResults(target, ...)
if err != nil {
    log.Printf("execute failed: %v", err)
}

Prevention

When it happens

Trigger: Windows AV scanning nuclei's temp copy at the instant of removal; a shared TMPDIR where another process deletes files; permission changes on the temp dir mid-scan.

Common situations: EDR-equipped Windows hosts; parallel runs sharing one TMPDIR; hardening policies that lock temp files.

Related errors


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

Appendix: source

Thrown at internal/runner/runner.go:720

		os.Exit(0)
	}

	if r.options.TemplateList || r.options.TemplateDisplay {
		if err := store.LoadTemplatesOnlyMetadata(); err != nil {
			return err
		}
		r.listAvailableStoreTemplates(store)
		os.Exit(0)
	}

	if r.options.Validate {
		if err := store.ValidateTemplates(); err != nil {
			return err
		}
		if stats.GetValue(templates.TemplateSyntaxErrorStats) == 0 && stats.GetValue(templates.TemplateSyntaxWarningStats) == 0 && stats.GetValue(templates.TemplateRuntimeWarningStats) == 0 {
			r.Logger.Info().Msgf("All templates validated successfully")
		} else {
			return errors.New("encountered errors while performing template validation")
		}
		return nil // exit
	}
	if err := store.Load(); err != nil {
		return err
	}
	// TODO: remove below functions after v3 or update warning messages
	templates.PrintDeprecatedProtocolNameMsgIfApplicable(r.options.Silent, r.options.Verbose)

	// add the hosts from the metadata queries of loaded templates into input provider
	if r.options.Uncover && len(r.options.UncoverQuery) == 0 {
		uncoverOpts := &uncoverlib.Options{
			Limit:         r.options.UncoverLimit,
			MaxRetry:      r.options.Retries,
			Timeout:       r.options.Timeout,
			RateLimit:     uint(r.options.UncoverRateLimit),
			RateLimitUnit: time.Minute, // default unit is minute
		}

View on GitHub (pinned to 265b3a3dec)