{"record":{"id":"d40f6a8aec4faa8d","repo":"projectdiscovery/nuclei","slug":"failed-to-store-flow-runtime-errors-got-v","errorCode":null,"errorMessage":"failed to store flow runtime errors got %v","messagePattern":"failed to store flow runtime errors got (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/tmplexec/flow/flow_internal.go","lineNumber":54,"sourceCode":"\t\t\t// transform input if required\n\t\t\tinputItem := f.ctx.Input.Clone()\n\t\t\tif f.options.InputHelper != nil && f.ctx.Input.MetaInput.Input != \"\" {\n\t\t\t\tif inputItem.MetaInput.Input = f.options.InputHelper.Transform(inputItem.MetaInput.Input, req.Type()); inputItem.MetaInput.Input == \"\" {\n\t\t\t\t\tf.ctx.LogError(fmt.Errorf(\"failed to transform input for protocol %s\", req.Type()))\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t\terr := req.ExecuteWithResults(inputItem, output.InternalEvent(f.options.GetTemplateCtx(f.ctx.Input.MetaInput).GetAll()), output.InternalEvent{}, f.protocolResultCallback(req, matcherStatus, opts))\n\t\t\tif err != nil {\n\t\t\t\t// save all errors in a map with id as key\n\t\t\t\t// its less likely that there will be race condition but just in case\n\t\t\t\tid := req.GetID()\n\t\t\t\tif id == \"\" {\n\t\t\t\t\tid, _ = reqMap.GetKeyWithValue(req)\n\t\t\t\t}\n\t\t\t\terr = f.allErrs.Set(opts.protoName+\":\"+id, err)\n\t\t\t\tif err != nil {\n\t\t\t\t\tf.ctx.LogError(fmt.Errorf(\"failed to store flow runtime errors got %v\", err))\n\t\t\t\t}\n\t\t\t\treturn matcherStatus.Load()\n\t\t\t}\n\t\t}\n\t\treturn matcherStatus.Load()\n\t}\n\n\t// execution logic for http(\"0\") or http(\"get-aws-vpcs\")\n\tfor _, id := range opts.reqIDS {\n\t\treq, ok := reqMap[id]\n\t\tif !ok {\n\t\t\tf.ctx.LogError(fmt.Errorf(\"[%v] invalid request id '%s' provided\", f.options.TemplateID, id))\n\t\t\t// compile error\n\t\t\tif err := f.allErrs.Set(opts.protoName+\":\"+id, errkit.Newf(\"[%s] invalid request id '%s' provided\", f.options.TemplateID, id)); err != nil {\n\t\t\t\tf.ctx.LogError(fmt.Errorf(\"failed to store flow runtime errors got %v\", err))\n\t\t\t}\n\t\t\treturn matcherStatus.Load()\n\t\t}","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/tmplexec/flow/flow_internal.go#L36-L72","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Nothing to catch — LogError only. In custom runners, filter the noise:\nfor _, e := range scanCtx.Errors() {\n    if strings.Contains(e.Error(), \"failed to store flow runtime errors\") {\n        continue // bookkeeping race; real signal is the adjacent protocol error\n    }\n    handle(e)\n}","preventionTips":["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"],"tags":["flow","error-handling","race","shutdown"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}