{"record":{"id":"6f359b2f6b9d87c1","repo":"shadow1ng/fscan","slug":"output-manager-is-closed","errorCode":null,"errorMessage":"output manager is closed","messagePattern":"output manager is closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/output/manager.go","lineNumber":77,"sourceCode":"\tdefault:\n\t\treturn fmt.Errorf(\"unsupported format: %s\", m.config.Format)\n\t}\n\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tm.writer = writer\n\treturn m.writer.WriteHeader()\n}\n\n// SaveResult 保存扫描结果\nfunc (m *Manager) SaveResult(result *ScanResult) error {\n\tm.mu.RLock()\n\tdefer m.mu.RUnlock()\n\n\tif m.closed {\n\t\treturn fmt.Errorf(\"output manager is closed\")\n\t}\n\n\tif result == nil {\n\t\treturn fmt.Errorf(\"result cannot be nil\")\n\t}\n\n\treturn m.writer.Write(result)\n}\n\n// Flush 刷新输出\nfunc (m *Manager) Flush() error {\n\tm.mu.RLock()\n\tdefer m.mu.RUnlock()\n\n\tif m.closed {\n\t\treturn fmt.Errorf(\"output manager is closed\")\n\t}\n","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/common/output/manager.go#L59-L95","documentation":"Guard in Manager.initializeWriter: the configured output format string matched none of txt/json/csv, so no Writer could be constructed. Usually preceded by an explicit format validation at the caller.","triggerScenarios":"Calling SaveResult after Manager.Close(); calling SaveResult concurrently while another goroutine closes the manager; reusing a manager across scan lifecycles without recreating it.","commonSituations":"Deferred Close() running before a late SaveResult, worker goroutines outliving the manager's lifetime, reusing one manager for a second scan run.","solutions":["Ensure all SaveResult calls complete before calling Close()","Create a new Manager instance for each scan run instead of reusing a closed one","Synchronize goroutines (WaitGroup/channel) so no writes happen after shutdown"],"exampleFix":"// before\nmgr.Close()\nmgr.SaveResult(res) // error\n// after\nmgr.SaveResult(res)\nmgr.Close()","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := mgr.SaveResult(res); err != nil {\n    if strings.Contains(err.Error(), \"output manager is closed\") {\n        return errors.New(\"attempted save after manager shutdown; ordering bug\")\n    }\n    return err\n}","preventionTips":["Call Close only after all SaveResult calls finish (use WaitGroup)","Never reuse a Manager after Close; construct a new one per run","Structure shutdown as: stop producers -> flush -> close"],"tags":["output","closed-resource","concurrency"],"backgroundTag":"invalid-state-transition","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}