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
- Look for the interrupt/shutdown correlation: this usually appears during Ctrl+C or scan teardown — treat as noise there
- Re-run at lower concurrency to see if the real protocol error surfaces without the bookkeeping race
- Update nuclei — SyncLockMap lifecycle around flow teardown has had fixes
- 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
- Don't treat this meta-error as the diagnosis — find the adjacent protocol failure
- Avoid interrupting scans mid-flight; finish or cancel before flow teardown windows
- Pin recent nuclei versions where flow teardown races were addressed
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
- could not compile flow: %s
- could not create flow executor: %s
- invalid request type %s
- panic occurred while executing flow: %v
- output callback cannot be nil
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/d40f6a8aec4faa8d.
Report an issue: GitHub.