{"record":{"id":"73e25d476072de8c","repo":"siyuan-note/siyuan","slug":"second-argument-must-be-a-function","errorCode":null,"errorMessage":"second argument must be a function","messagePattern":"second argument must be a function","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_rpc.go","lineNumber":60,"sourceCode":"\t\tvar name string\n\t\tvar method goja.Callable\n\t\tvar descriptions []string\n\t\tif len(call.Arguments) < 2 {\n\t\t\targErr = fmt.Errorf(\"method name and function required\")\n\t\t} else {\n\t\t\tnameArg := call.Argument(0)\n\t\t\tmethodArg := call.Argument(1)\n\t\t\tdescArgs := call.Arguments[2:]\n\t\t\tif goja.IsString(nameArg) {\n\t\t\t\tname = nameArg.String()\n\t\t\t} else {\n\t\t\t\targErr = fmt.Errorf(\"first argument must be method name string\")\n\t\t\t}\n\t\t\tif argErr == nil {\n\t\t\t\tif methodJs, ok := goja.AssertFunction(methodArg); ok {\n\t\t\t\t\tmethod = methodJs\n\t\t\t\t} else {\n\t\t\t\t\targErr = fmt.Errorf(\"second argument must be a function\")\n\t\t\t\t}\n\t\t\t}\n\t\t\tif argErr == nil {\n\t\t\t\tdescriptions = make([]string, len(descArgs))\n\t\t\t\tfor i, a := range descArgs {\n\t\t\t\t\tdescriptions[i] = a.String()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trunErr := p.worker.Run(func(rt *goja.Runtime) (result any, err error) {\n\t\t\tif argErr != nil {\n\t\t\t\terr = argErr\n\t\t\t\treturn\n\t\t\t}\n\t\t\terr = p.bindRpcMethod(name, method, descriptions...)\n\t\t\treturn\n\t\t}, func(rt *goja.Runtime, result any, err error) {","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_rpc.go#L42-L78","documentation":"Thrown by siyuan.rpc.bind when the second argument is not callable. bind needs a function to invoke when the RPC method is called; goja.AssertFunction fails for non-function values.","triggerScenarios":"Calling bind('add', 'description'), bind('add', {}), or bind('add', null).","commonSituations":"Plugin passes a description string in the handler slot, or the handler reference is undefined when bind runs.","solutions":["Pass a function as the second argument: siyuan.rpc.bind('add', (params) => ...).","Ensure the handler reference is not undefined before binding."],"exampleFix":"// before\nsiyuan.rpc.bind('add', 'adds two numbers');\n// after\nsiyuan.rpc.bind('add', (params) => params.a + params.b, 'adds two numbers');","handlingStrategy":"type-guard","validationCode":"if (typeof fn !== 'function') throw new TypeError('handler must be a function');\nsiyuan.rpc.bind(name, fn);","typeGuard":"const isHandler = (v) => typeof v === 'function';","tryCatchPattern":null,"preventionTips":["Verify the handler is a function before bind.","Put descriptions after the handler, not in its place."],"tags":["rpc","bind","validation","type","function"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}