{"record":{"id":"23e6655fbe556796","repo":"siyuan-note/siyuan","slug":"method-name-required","errorCode":null,"errorMessage":"method name required","messagePattern":"method name required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_rpc.go","lineNumber":105,"sourceCode":"\t\t\t}\n\t\t})\n\t\tif runErr != nil {\n\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.rpc.bind worker run: %v\", p.Name, runErr)\n\t\t\tif rejectErr := reject(rt.NewGoError(runErr)); rejectErr != nil {\n\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.rpc.bind reject: %v\", p.Name, rejectErr)\n\t\t\t}\n\t\t}\n\n\t\treturn rt.ToValue(promise)\n\t})))\n\n\tlo.Must0(rpc.Set(\"unbind\", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {\n\t\tpromise, resolve, reject := rt.NewPromise()\n\n\t\tvar argErr error\n\t\tvar name string\n\t\tif len(call.Arguments) < 1 {\n\t\t\targErr = fmt.Errorf(\"method name required\")\n\t\t} else if nameArg := call.Argument(0); goja.IsString(nameArg) {\n\t\t\tname = nameArg.String()\n\t\t} else {\n\t\t\targErr = fmt.Errorf(\"first argument must be method name string\")\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.unbindRpcMethod(name)\n\t\t\treturn\n\t\t}, func(rt *goja.Runtime, result any, err error) {\n\t\t\tif lo.IsNil(err) {\n\t\t\t\tif resolveErr := resolve(result); resolveErr != nil {\n\t\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.rpc.unbind resolve: %v\", p.Name, resolveErr)\n\t\t\t\t}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_rpc.go#L87-L123","documentation":"The siyuan.rpc.unbind API removes a previously bound RPC method by name. It requires at least one call argument; when none is provided it rejects the returned promise with 'method name required'. The kernel cannot identify which binding to remove without a name.","triggerScenarios":"Calling siyuan.rpc.unbind() with zero arguments.","commonSituations":"Copy-pasted unbind call where the name argument was deleted; dynamically computing the name and the expression evaluating to undefined so the argument list effectively appears empty in checks; template-string bug producing an empty call.","solutions":["Pass the method name string as the first argument: siyuan.rpc.unbind('myMethod')","Verify the name expression is not undefined before the call","Guard the call site: only call unbind when a name was actually bound"],"exampleFix":"// before\nawait siyuan.rpc.unbind()\n// after\nawait siyuan.rpc.unbind('myMethod')","handlingStrategy":"validation","validationCode":"if (typeof name === 'string' && name) { await siyuan.rpc.unbind(name) }","typeGuard":"const hasName = (v) => typeof v === 'string' && v.length > 0","tryCatchPattern":"try { await siyuan.rpc.unbind(name) } catch (e) { if (e.message !== 'method name required') throw e }","preventionTips":["Keep bound method names in a constants list and unbind from it","Never call unbind with zero arguments","Track bindings in a Set so unbind is only called for known names"],"tags":["javascript","rpc","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}