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
- Choose a different (free) Position for the exclusive handler
- Set Exclusive=false if sharing the position with other handlers is acceptable
- Inventory existing registered handlers per EventType/Position before assigning positions
- 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
- Document and allocate positions across all plugins to avoid collisions
- Only mark handlers Exclusive when they truly must own a position
- Keep Position within 1..50 (the registry clamps, but out-of-range invites conflicts)
- Check whether a built-in plugin already claims the position before choosing it
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
- handler %s already registered for EventType %s
- failed to obtain the Amass output directory
- failed to create the RDAP disk cache
- zero locations found
- failed to extract the locations
AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06).
Data as JSON: /api/errors/07d7776111f41d4f.
Report an issue: GitHub.