{"record":{"id":"bc49adabcbc0b898","repo":"siyuan-note/siyuan","slug":"method-required","errorCode":null,"errorMessage":"method required","messagePattern":"method required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_rpc.go","lineNumber":147,"sourceCode":"\t\t})\n\t\tif runErr != nil {\n\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.rpc.unbind 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.unbind 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(\"broadcast\", 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 method string\n\t\tvar params util.Optional[any]\n\t\tif len(call.Arguments) < 1 {\n\t\t\targErr = fmt.Errorf(\"method required\")\n\t\t} else {\n\t\t\tif m := call.Argument(0); goja.IsString(m) {\n\t\t\t\tmethod = m.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\targ := call.Argument(1)\n\t\t\t\tif goja.IsUndefined(arg) {\n\t\t\t\t\tparams.Value = nil\n\t\t\t\t\tparams.Exists = false\n\t\t\t\t\tparams.IsNull = false\n\t\t\t\t} else if goja.IsNull(arg) {\n\t\t\t\t\tparams.Value = nil\n\t\t\t\t\tparams.Exists = true\n\t\t\t\t\tparams.IsNull = true\n\t\t\t\t} else {\n\t\t\t\t\tparams.Value = arg.Export()","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_rpc.go#L129-L165","documentation":"This is the siyuan.server-style RPC request API in api_rpc.go: it requires the target method name as its first argument. With zero arguments the promise rejects with 'method required' because there is nothing to dispatch to. The call is asynchronous; the error surfaces via the returned promise.","triggerScenarios":"Calling the RPC request function with no arguments, e.g. rpc() or rpc() after spreading an empty array: rpc(...[]).","commonSituations":"Building the argument list dynamically from config and the config being empty; forgetting the method argument when only params were intended; a refactor that moved the method name into an options object the kernel does not accept.","solutions":["Pass the method name string as the first argument: rpc('methodName')","If params are needed, pass them as the second argument: rpc('methodName', params)","Validate the dynamic argument array is non-empty before spreading it into the call"],"exampleFix":"// before\nconst args = []\nawait siyuan.rpc(...args)\n// after\nawait siyuan.rpc('methodName', { foo: 1 })","handlingStrategy":"validation","validationCode":"if (args.length === 0) throw new Error('rpc requires a method name')\nawait siyuan.rpc(...args)","typeGuard":null,"tryCatchPattern":"try { await siyuan.rpc(method, params) } catch (e) { if (e.message === 'method required') { /* fix call site */ } else throw e }","preventionTips":["Always call rpc with a literal method name first argument","Validate dynamically built argument arrays before spreading","Centralize rpc calls in a wrapper that asserts the method name"],"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"}