owasp-amass/amass · error

handler at position %d already registered for EventType %s

Error message

handler at position %d already registered for EventType %s

What it means

Registry.RegisterHandler rejects a handler with Exclusive=true whose (EventType, Position) slot already holds at least one handler. Exclusive handlers claim a position on an event type; the engine clamps Position to [1,50] and errors if the slot is taken, logging the failure and returning the error.

Source

Thrown at engine/registry/registry.go:69

			}
		}
	}
	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
	}

	r.handlers[atype][p] = append(r.handlers[atype][p], h)
	return nil
}

View on GitHub (pinned to 79299dce87)

Solutions

  1. Choose a different (free) Position for the exclusive handler
  2. Set Exclusive=false if sharing the position with other handlers is acceptable
  3. Inventory existing registered handlers per EventType/Position before assigning positions
  4. Ensure plugins are not started twice, which would collide with their own exclusive slot

Example fix

// before
&et.Handler{Name: "asn", EventType: oam.Netblock, Position: 2, Exclusive: true} // slot 2 taken
// after
&et.Handler{Name: "asn", EventType: oam.Netblock, Position: 3, Exclusive: true} // free slot
Defensive patterns

Strategy: validation

Validate before calling

// before registering an exclusive handler, reserve/free the slot
const maxPos = 50
func positionFree(reg *registry.Registry, eventType string, pos int) bool {
    if pos < 1 || pos > maxPos { return false }
    return len(reg.HandlersAt(eventType, pos)) == 0
}

Try / catch

if err := registry.RegisterHandler(h); err != nil {
    if strings.Contains(err.Error(), "already registered") {
        h.Position++ // or set Exclusive=false and retry once
        return registry.RegisterHandler(h)
    }
    return err
}

Prevention

When it happens

Trigger: Calling RegisterHandler with h.Exclusive=true and h.Position = N where r.handlers[EventType][N] already contains handlers — e.g. two exclusive handlers both claiming position 2 for oam.Netblock, or a built-in plugin already occupying the slot your custom handler requests.

Common situations: Custom plugin registering at the same position as a built-in plugin's exclusive handler; two copies of the same plugin both claiming an exclusive slot; changing a plugin to Exclusive while another handler occupies its position; misconfigured Position values colliding across plugins.

Related errors


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