siyuan-note/siyuan · error
registerCapability requires 3 arguments: name, config…
Error message
registerCapability requires 3 arguments: name, config, handler
What it means
registerCapability() is the plugin API for registering an agent tool/capability with the kernel. It requires exactly three arguments: a name string, a config object, and a handler function. The runtime throws this error before doing any work when fewer than three arguments are passed, because a capability cannot be registered without all three pieces.
Solutions
- Pass all three arguments in order: registerCapability(name, config, handler)
- Define the handler function and the config object before the call site
- Log typeof each argument (string, object, function) before calling to spot the missing one
Example fix
// before
plugin.registerCapability("my_tool", { description: "..." });
// after
plugin.registerCapability("my_tool", { description: "...", inputSchema: {...} }, async (args) => { return { content: "ok" }; }); Defensive patterns
Strategy: validation
Validate before calling
function canRegister(args) { return Array.isArray(args) && args.length >= 3; }
if (!canRegister([name, config, handler])) throw new Error("registerCapability needs (name, config, handler)"); Type guard
const isRegisterable = (n, c, h) => typeof n === "string" && n.trim() !== "" && c !== null && typeof c === "object" && typeof h === "function";
Try / catch
try { plugin.registerCapability(name, config, handler); } catch (e) { if (String(e).includes("registerCapability requires 3 arguments")) { /* fix arg count */ } else { throw e; } } Prevention
- Always call with the full triple (name, config, handler)
- Define config and handler above the registration call
- Wrap registration in a helper that validates arity once
When it happens
Trigger: Calling registerCapability(name, config) with only two arguments, registerCapability(name) with one, or registerCapability() with none — e.g. omitting the handler callback or forgetting the config object in the call.
Common situations: Copy-pasted plugin sample code where the handler was trimmed; refactoring that removed the config argument; dynamically-built argument lists where an optional value ended up undefined; typos in a wrapper function that forwards arguments incorrectly.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- unregisterCapability requires 1 argument: name
- capability name must not be empty
- config.description is required and must be a string
- config.description must not be empty
- config.inputSchema is required
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/ab43c454dc19fb87.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/api_agent.go:70
agentAPI := rt.NewObject()
// siyuan.agent.registerCapability(name, config, handler) 返回 Promise<IRegisteredCapability>。
lo.Must0(agentAPI.Set("registerCapability", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
promise, resolve, reject := rt.NewPromise()
var name string
var title string
var description string
var effects *tools.ToolEffects
var actionEffects map[string]tools.ToolEffects
var inputSchema *tools.ToolSchema
var outputSchema *tools.ToolSchema
var handler goja.Callable
argErr := func() (err error) {
if len(call.Arguments) < 3 {
err = fmt.Errorf("registerCapability requires 3 arguments: name, config, handler")
return
} else {
if s := call.Argument(0); goja.IsString(s) {
name = strings.TrimSpace(s.String())
if name == "" {
err = fmt.Errorf("capability name must not be empty")
return
}
} else {
err = fmt.Errorf("first argument must be a tool name string")
return
}
if c := call.Argument(1); isJsValueNotNull(c) {
configObj := c.ToObject(rt)
if configObj != nil {
if titleValue := configObj.Get("title"); goja.IsString(titleValue) {
title = titleValue.String()View on GitHub (pinned to 9f775e8a12)