{"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/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_rpc.go#L129-L165","documentation":"Thrown by siyuan.rpc.broadcast() when called with no arguments. broadcast dispatches an RPC method invocation to all loaded plugins (inter-plugin messaging) and needs a method name string to route the call. With zero arguments there is no method to invoke, so the promise rejects before any dispatch.","triggerScenarios":"await siyuan.rpc.broadcast() with an empty call, or broadcast called via .apply(ctx, []) where the arguments array was unexpectedly empty.","commonSituations":"Plugin builds its broadcast call from a config object whose 'method' field is optional and was omitted; or the developer confused broadcast (fan-out) with a no-arg ping and called it bare.","solutions":["Pass the target method name string as the first argument, e.g. broadcast('pluginB.onEvent').","If the params are optional, still always include the method name as argument 0.","Validate the method identifier is non-empty before broadcasting."],"exampleFix":"// before\nawait siyuan.rpc.broadcast();\n// after\nawait siyuan.rpc.broadcast('myPlugin.onData', { payload: 1 });","handlingStrategy":"validation","validationCode":"if (arguments.length === 0 || typeof arguments[0] !== 'string') {\n  throw new TypeError('broadcast requires a method name string');\n}","typeGuard":"const isBroadcastTarget = (v) => typeof v === 'string' && v.length > 0;","tryCatchPattern":"try { await siyuan.rpc.broadcast(method, params); }\ncatch (e) { if (/method required/.test(String(e))) { /* method omitted: skip */ } else throw e; }","preventionTips":["Always pass the method name as the first positional argument even when params are optional.","Validate config-driven method identifiers before broadcasting."],"tags":["plugin-api","rpc","broadcast","argument-validation","javascript"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}