wailsapp/wails · error
binding method ID registration expects a function, got %s
Error message
binding method ID registration expects a function, got %s
What it means
RegisterBindingMethodID stores a stable numeric ID for a service method so the runtime can resolve bound calls even when binary obfuscation (e.g. garble) strips reflection-visible names. It reflects on the passed value and panics if it is not a func, since the ID is keyed on the function's code pointer.
Source
Thrown at v3/pkg/application/bindings.go:101
isVariadic bool // cached at registration to avoid reflect call per invocation
}
type Bindings struct {
marshalError func(error) []byte
boundMethods map[string]*BoundMethod
boundByID map[uint32]*BoundMethod
methodAliases map[uint32]uint32
}
var registeredBindingMethodIDs sync.Map
// RegisterBindingMethodID registers a stable binding ID for a service method
// expression so the runtime can resolve it without relying on reflection-visible
// names (which may be obfuscated).
func RegisterBindingMethodID(method any, id uint32) {
value := reflect.ValueOf(method)
if value.Kind() != reflect.Func {
panic(fmt.Sprintf("binding method ID registration expects a function, got %s", value.Kind()))
}
registeredBindingMethodIDs.Store(value.Pointer(), id)
}
// UnregisterBindingMethodID removes the stable binding ID for a service method.
// Intended for use in tests to restore global state after calling RegisterBindingMethodID.
func UnregisterBindingMethodID(method any) {
value := reflect.ValueOf(method)
if value.Kind() != reflect.Func {
return
}
registeredBindingMethodIDs.Delete(value.Pointer())
}
func getRegisteredBindingMethodID(method reflect.Method) (uint32, bool) {
id, ok := registeredBindingMethodIDs.Load(method.Func.Pointer())
if !ok {
return 0, falseView on GitHub (pinned to 0e754b1b40)
Solutions
- Pass the method value itself: app.RegisterBindingMethodID(svc.GetUsers, id)
- Do not pass the receiver, a string name, or a nil value
- Keep the argument a first-class func so value.Pointer() is a valid code address
Example fix
// before
app.RegisterBindingMethodID("GetUsers", 42) // string: panics
app.RegisterBindingMethodID(userSvc, 42) // struct: panics
// after
app.RegisterBindingMethodID(userSvc.GetUsers, 42) // method value: OK Defensive patterns
Strategy: type-guard
Validate before calling
if reflect.ValueOf(method).Kind() != reflect.Func {
return fmt.Errorf("RegisterBindingMethodID needs a method value, got %T", method)
}
app.RegisterBindingMethodID(method, id) Type guard
func registerBindingID[F func(...any) (any, error)](app *application.App, method F, id uint32) {
app.RegisterBindingMethodID(method, id) // non-func cannot compile
} Prevention
- Always pass the bare method value: svc.Method, not "Method", svc, or &svc.Method
- Add a tiny typed wrapper so the compiler enforces func arguments
When it happens
Trigger: Passing anything other than a method value / function to RegisterBindingMethodID — e.g. a struct instance, a method name string, or a nil any.
Common situations: Setting up obfuscation-resistant bindings and passing svc.SomeMethod() result incorrectly (e.g. &svc.SomeMethod, svc (the struct), or "SomeMethod" instead of the bare method value).
Related errors
- Values for %T isn't a slice
- missing Type field in
- missing TSName field in
- has no TSName method
- use ShowAndGetResults for open multiple files dialog
AI-assisted analysis of wailsapp/wails@0e754b1b40 (2026-08-15).
Data as JSON: /api/errors/d4b2bee20f8fc80b.
Report an issue: GitHub.