{"record":{"id":"735951fa6c77a0bf","repo":"siyuan-note/siyuan","slug":"first-argument-must-be-method-name-string","errorCode":null,"errorMessage":"first argument must be method name string","messagePattern":"first argument must be method name string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_rpc.go","lineNumber":54,"sourceCode":"\trpc := rt.NewObject()\n\n\tlo.Must0(rpc.Set(\"bind\", 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\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 {","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/plugin/api_rpc.go#L36-L72","documentation":"siyuan.rpc.bind validates argument types: the first argument must be a string method name (and, next, the second must be a function). When the first argument is not a string, the call is rejected with this error. The follow-on check for the second argument produces 'second argument must be a function'.","triggerScenarios":"Calling rpc.bind({name: 'x'}, fn), rpc.bind(fn, fn), or rpc.bind(123, fn) — any non-string first argument.","commonSituations":"Passing a config object as the first argument assuming an object-based API; swapping argument order; passing a Symbol/enum-like name value instead of a string.","solutions":["Pass the method name as a plain string: bind('myMethod', fn)","Reorder arguments if name and handler were swapped","Convert a non-string name with String(name) only if it is genuinely a name value","Check the upstream variable producing the name for unexpected types"],"exampleFix":"// before\nsiyuan.rpc.bind({name: 'myMethod'}, handler);\n// after\nsiyuan.rpc.bind('myMethod', handler);","handlingStrategy":"type-guard","validationCode":"function bindRpc(name, handler, ...descs) {\n  if (typeof name !== 'string') {\n    throw new TypeError('rpc.bind first argument must be a method name string');\n  }\n  if (typeof handler !== 'function') {\n    throw new TypeError('rpc.bind second argument must be a function');\n  }\n  return siyuan.rpc.bind(name, handler, ...descs);\n}","typeGuard":"function isRpcName(v) {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":"try {\n  siyuan.rpc.bind(name, handler);\n} catch (e) {\n  if (String(e.message).includes('first argument must be method name string')) {\n    console.error('rpc.bind name must be a string, got:', typeof name, name);\n  }\n  throw e;\n}","preventionTips":["Never pass config objects to rpc.bind; use a plain string name","Keep the (name, handler, ...descriptions) argument order","Stringify name-like values explicitly at the call boundary if they come from external data"],"tags":["plugin","rpc","type-mismatch","validation"],"backgroundTag":"type-mismatch","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"}