owasp-amass/amass · error

handler %s already registered for EventType %s

Error message

handler %s already registered for EventType %s

What it means

Registry.RegisterHandler rejects a handler whose (Name, EventType) pair is already registered. The engine forbids duplicate named handlers for the same event type to keep event-dispatch deterministic; it logs the failure via the registry logger and returns the error to the caller (the plugin's Start/OnStart).

Source

Thrown at engine/registry/registry.go:55

	defer r.Unlock()

	// is the entry for the requested event type currently empty?
	if _, found := r.handlers[h.EventType]; !found {
		r.handlers[h.EventType] = make(map[int][]*et.Handler)
	}
	// has this registration been made already?
	var found bool
loop:
	for _, handlers := range r.handlers[h.EventType] {
		for _, handler := range handlers {
			if handler.Name == h.Name {
				found = true
				break loop
			}
		}
	}
	if found {
		err := fmt.Errorf("handler %s already registered for EventType %s", h.Name, h.EventType)
		r.Log().Error(fmt.Sprintf("Failed to register a handler: %v", err),
			slog.Group("plugin", "name", h.Plugin.Name(), "handler", h.Name))
		return err
	}

	if h.Position <= 0 {
		h.Position = 1
	} else if h.Position > 50 {
		h.Position = 50
	}

	atype, p := h.EventType, h.Position
	if handlers, found := r.handlers[atype][p]; found && len(handlers) > 0 && h.Exclusive {
		err := fmt.Errorf("handler at position %d already registered for EventType %s", p, atype)
		r.Log().Error(fmt.Sprintf("Failed to register a handler: %v", err),
			slog.Group("plugin", "name", h.Plugin.Name(), "handler", h.Name))
		return err
	}

View on GitHub (pinned to 79299dce87)

Solutions

  1. Check whether the plugin/engine was already started and skip or stop it before re-registering
  2. Ensure each Handler has a unique Name per EventType across all plugins
  3. Call Stop/unregister for existing handlers before re-registering in reload logic
  4. Call RegisterHandler only once per handler instance during initialization

Example fix

// before
if err := engine.Start(); err != nil { ... } // plugin re-registered on restart
// after
if err := engine.Stop(); err != nil { ... }
if err := engine.Start(); err != nil { ... } // unregister before re-register
Defensive patterns

Strategy: try-catch

Validate before calling

// check before registering (pseudo-API)
if registry.IsRegistered(handler.Name, handler.EventType) {
    return fmt.Errorf("handler %s for %s already registered", handler.Name, handler.EventType)
}
// also guard against double-start
if engine.IsRunning() { return nil }

Try / catch

if err := engine.Start(); err != nil {
    if strings.Contains(err.Error(), "already registered") {
        // skip re-registration or stop & restart engine first
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Calling RegisterHandler (directly or via a plugin's Start) with a Handler whose Name and EventType match an already-registered handler — e.g. starting the same plugin twice, or two handlers sharing a name for the same EventType.

Common situations: Calling engine.Start()/plugin Start() twice without stopping; registering the same handler instance again after a failed start partially succeeded; two custom plugins accidentally using the same handler name for the same event type; hot-reload code re-registering handlers.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06). Data as JSON: /api/errors/fc65c55abb5c2955. Report an issue: GitHub.