shadow1ng/fscan · error

output manager is closed

Error message

output manager is closed

What it means

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.

Source

Thrown at common/output/manager.go:77

	default:
		return fmt.Errorf("unsupported format: %s", m.config.Format)
	}

	if err != nil {
		return err
	}

	m.writer = writer
	return m.writer.WriteHeader()
}

// SaveResult 保存扫描结果
func (m *Manager) SaveResult(result *ScanResult) error {
	m.mu.RLock()
	defer m.mu.RUnlock()

	if m.closed {
		return fmt.Errorf("output manager is closed")
	}

	if result == nil {
		return fmt.Errorf("result cannot be nil")
	}

	return m.writer.Write(result)
}

// Flush 刷新输出
func (m *Manager) Flush() error {
	m.mu.RLock()
	defer m.mu.RUnlock()

	if m.closed {
		return fmt.Errorf("output manager is closed")
	}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Ensure all SaveResult calls complete before calling Close()
  2. Create a new Manager instance for each scan run instead of reusing a closed one
  3. Synchronize goroutines (WaitGroup/channel) so no writes happen after shutdown

Example fix

// before
mgr.Close()
mgr.SaveResult(res) // error
// after
mgr.SaveResult(res)
mgr.Close()
Defensive patterns

Strategy: validation

Try / catch

if err := mgr.SaveResult(res); err != nil {
    if strings.Contains(err.Error(), "output manager is closed") {
        return errors.New("attempted save after manager shutdown; ordering bug")
    }
    return err
}

Prevention

When it happens

Trigger: Calling SaveResult after Manager.Close(); calling SaveResult concurrently while another goroutine closes the manager; reusing a manager across scan lifecycles without recreating it.

Common situations: Deferred Close() running before a late SaveResult, worker goroutines outliving the manager's lifetime, reusing one manager for a second scan run.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/6f359b2f6b9d87c1. Report an issue: GitHub.