{"record":{"id":"cac3b9c9d755a392","repo":"bettercap/bettercap","slug":"onstart-signature-does-not-match-expected-signatur","errorCode":null,"errorMessage":"OnStart signature does not match expected signature: 'func() int'","messagePattern":"OnStart signature does not match expected signature: 'func\\(\\) int'","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/packet_proxy/packet_proxy_linux.go","lineNumber":159,"sourceCode":"\t\t}\n\n\t\tmod.Info(\"loading packet proxy plugin from %s ...\", mod.pluginPath)\n\n\t\tvar ok bool\n\t\tvar sym plugin.Symbol\n\n\t\tif mod.plugin, err = plugin.Open(mod.pluginPath); err != nil {\n\t\t\treturn\n\t\t} else if sym, err = mod.plugin.Lookup(\"OnPacket\"); err != nil {\n\t\t\treturn\n\t\t} else if mod.queueCb, ok = sym.(func(q *nfqueue.Nfqueue, a nfqueue.Attribute) int); !ok {\n\t\t\treturn fmt.Errorf(\"Symbol OnPacket is not a valid callback function.\")\n\t\t}\n\n\t\tif sym, err = mod.plugin.Lookup(\"OnStart\"); err == nil {\n\t\t\tvar onStartCb func() int\n\t\t\tif onStartCb, ok = sym.(func() int); !ok {\n\t\t\t\treturn fmt.Errorf(\"OnStart signature does not match expected signature: 'func() int'\")\n\t\t\t} else {\n\t\t\t\tvar result int\n\t\t\t\tif result = onStartCb(); result != 0 {\n\t\t\t\t\treturn fmt.Errorf(\"OnStart returned non-zero result. result=%d\", result)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tmod.Warning(\"no plugin set\")\n\t}\n\n\tconfig := nfqueue.Config{\n\t\tNfQueue:      uint16(mod.queueNum),\n\t\tCopymode:     nfqueue.NfQnlCopyPacket,\n\t\tAfFamily:     syscall.AF_INET,\n\t\tMaxPacketLen: 0xFFFF,\n\t\tMaxQueueLen:  0xFF,\n\t\tWriteTimeout: 15 * time.Millisecond,","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/bettercap/bettercap/blob/8eca2820f3c41d2004434ed5a291d87462caeeb7/modules/packet_proxy/packet_proxy_linux.go#L141-L177","documentation":"If the plugin also exports OnStart, packet.proxy asserts it to func() int and calls it during Configure. A non-nil OnStart symbol with any other signature fails the type assertion and Configure returns this error quoting the expected signature.","triggerScenarios":"Plugin exports OnStart with parameters, a different return type (e.g. error instead of int), or as a non-function symbol; Lookup succeeds but the assertion to func() int fails.","commonSituations":"Plugin authors return error from OnStart out of habit, or add context parameters; stale plugin compiled from older example code with a different OnStart shape.","solutions":["Make the plugin's OnStart exactly: func OnStart() int","Return 0 on success, non-zero on failure inside the plugin","Rebuild the plugin with the same Go version as the host bettercap binary","If no startup hook is needed, remove OnStart entirely (Lookup failing is handled gracefully)"],"exampleFix":"// before (plugin)\nfunc OnStart(cfg Config) error { ... }\n// after\nfunc OnStart() int { setup(); return 0 }","handlingStrategy":"type-guard","validationCode":"// before shipping the plugin, assert OnStart's shape at build time:\n// var _ func() int = OnStart","typeGuard":"func isOnStart(sym plugin.Symbol) bool {\n    _, ok := sym.(func() int)\n    return ok\n}","tryCatchPattern":"if err := mod.Start(); err != nil {\n    if strings.Contains(err.Error(), \"OnStart signature\") {\n        log.Fatalf(\"plugin OnStart must be exactly func() int; got another shape\")\n    }\n    return err\n}","preventionTips":["Declare OnStart strictly as func OnStart() int — no params, int return","Add var _ func() int = OnStart in the plugin for compile-time checking","Rebuild the plugin whenever bettercap's expected hook signatures change"],"tags":["go","plugins","type-mismatch","nfqueue"],"backgroundTag":"plugin-symbol-type-mismatch","analyzedSha":"8eca2820f3c41d2004434ed5a291d87462caeeb7","analyzedAt":"2026-09-02T12:49:00.712Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}