wailsapp/wails · error
event '%s' is already registered with data type %s
Error message
event '%s' is already registered with data type %s
What it means
RegisterEvent[Data] panics when the same event name is already present in the registeredEvents store, reporting the data type it was first registered with. Events may be registered at most once because the binding generator emits a single TypeScript type per name and the data type must be unambiguous.
Source
Thrown at v3/pkg/application/events.go:307
var voidType = reflect.TypeFor[Void]()
// RegisterEvent registers a custom event name and associated data type.
// Events may be registered at most once.
// Duplicate calls for the same event name trigger a panic.
//
// The binding generator emits typing information for all registered custom events.
// [App.EmitEvent] and [Window.EmitEvent] check the data type for registered events.
// Data types are matched exactly and no conversion is performed.
//
// It is recommended to call RegisterEvent directly,
// with constant arguments, and only from init functions.
// Indirect calls or instantiations are not discoverable by the binding generator.
func RegisterEvent[Data any](name string) {
if events.IsKnownEvent(name) {
panic(fmt.Errorf("'%s' is a known system event name", name))
}
if typ, ok := registeredEvents.Load(name); ok {
panic(fmt.Errorf("event '%s' is already registered with data type %s", name, typ))
}
registeredEvents.Store(name, reflect.TypeFor[Data]())
eventRegistered(name)
}
func validateCustomEvent(event *CustomEvent) error {
r, ok := registeredEvents.Load(event.Name)
if !ok {
warnAboutUnregisteredEvent(event.Name)
return nil
}
typ := r.(reflect.Type)
if typ == voidType {
if event.Data == nil {
return nilView on GitHub (pinned to 0e754b1b40)
Solutions
- Register each event exactly once, ideally in a single init() with constant arguments as the docs recommend
- In tests, guard registration with sync.OnceValue or a package-level once, or skip re-registration
- If two features need similar events, give them distinct names instead of reusing one
Example fix
// before
func init() { app.RegisterEvent[LoginData]("user-login") }
func TestX(t *testing.T) { app.RegisterEvent[LoginData]("user-login") } // panics
// after
var registerEvents = sync.OnceValue(func() {
app.RegisterEvent[LoginData]("user-login")
})
func init() { registerEvents() }
func TestX(t *testing.T) { registerEvents() } Defensive patterns
Strategy: validation
Validate before calling
// guard double registration (mirror of the internal map check)
var eventOnce sync.Once
func registerAppEvents() {
eventOnce.Do(func() { app.RegisterEvent[LoginData]("myapp:user-login") })
} Prevention
- Register each event exactly once, in one init(), with constant arguments
- Use sync.OnceValue in tests that may re-run registration
- Give distinct names to semantically distinct events instead of reusing one
When it happens
Trigger: Calling RegisterEvent twice for the same name — from two packages' init functions, from init plus main, or across test runs in the same process (tests that re-run init or re-register without cleanup).
Common situations: Test suites that call RegisterEvent per test without compensating cleanup; refactoring so two init() blocks both register the same event; registering the same name with a different data type in a second module.
Related errors
- '%s' is a known system event name
- use ShowAndGetResults for open multiple files dialog
- use ShowAndGetResult for open single file dialog
- use GetResults for open multiple files dialog
- use GetResult for open single file dialog
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/4675b021e3b296aa.
Report an issue: GitHub.