projectdiscovery/nuclei · warning

failed to store flow runtime errors got %v

Error message

failed to store flow runtime errors got %v

What it means

A secondary error in flow_internal.go: when a protocol request fails (req.ExecuteWithResults returned an error), the flow tries to record it in the allErrs SyncLockMap keyed by protocol:id. If that Set itself fails, nuclei logs 'failed to store flow runtime errors got %v' — meaning the real protocol error was dropped and only this meta-failure is visible. SyncLockMap.Set fails when the map has been marked ReadOnly (post-close) or its lock is in a bad state.

Source

Thrown at pkg/tmplexec/flow/flow_internal.go:54

			// transform input if required
			inputItem := f.ctx.Input.Clone()
			if f.options.InputHelper != nil && f.ctx.Input.MetaInput.Input != "" {
				if inputItem.MetaInput.Input = f.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == "" {
					f.ctx.LogError(fmt.Errorf("failed to transform input for protocol %s", req.Type()))
					return false
				}
			}
			err := req.ExecuteWithResults(inputItem, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), output.InternalEvent{}, f.protocolResultCallback(req, matcherStatus, opts))
			if err != nil {
				// save all errors in a map with id as key
				// its less likely that there will be race condition but just in case
				id := req.GetID()
				if id == "" {
					id, _ = reqMap.GetKeyWithValue(req)
				}
				err = f.allErrs.Set(opts.protoName+":"+id, err)
				if err != nil {
					f.ctx.LogError(fmt.Errorf("failed to store flow runtime errors got %v", err))
				}
				return matcherStatus.Load()
			}
		}
		return matcherStatus.Load()
	}

	// execution logic for http("0") or http("get-aws-vpcs")
	for _, id := range opts.reqIDS {
		req, ok := reqMap[id]
		if !ok {
			f.ctx.LogError(fmt.Errorf("[%v] invalid request id '%s' provided", f.options.TemplateID, id))
			// compile error
			if err := f.allErrs.Set(opts.protoName+":"+id, errkit.Newf("[%s] invalid request id '%s' provided", f.options.TemplateID, id)); err != nil {
				f.ctx.LogError(fmt.Errorf("failed to store flow runtime errors got %v", err))
			}
			return matcherStatus.Load()
		}

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Look for the interrupt/shutdown correlation: this usually appears during Ctrl+C or scan teardown — treat as noise there
  2. Re-run at lower concurrency to see if the real protocol error surfaces without the bookkeeping race
  3. Update nuclei — SyncLockMap lifecycle around flow teardown has had fixes
  4. If reproducible on a quiet network, capture the full log and report to projectdiscovery/nuclei with the template and target count
Defensive patterns

Strategy: fallback

Try / catch

// Nothing to catch — LogError only. In custom runners, filter the noise:
for _, e := range scanCtx.Errors() {
    if strings.Contains(e.Error(), "failed to store flow runtime errors") {
        continue // bookkeeping race; real signal is the adjacent protocol error
    }
    handle(e)
}

Prevention

When it happens

Trigger: A protocol request errors (network failure, bad request build) at the same moment the allErrs map is being closed or flipped ReadOnly — typically during concurrent template teardown or an engine shutdown race. The primary error path and the bookkeeping path collide.

Common situations: Large scans with -c high concurrency where the runner is shutting down (context cancelled, interrupt) while in-flight flow requests error out; rare enough that most users never see it; when seen, the underlying protocol error is masked.

Related errors


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