siyuan-note/siyuan · error

registerCapability requires 3 arguments: name, config, handl

Error message

registerCapability requires 3 arguments: name, config, handler

What it means

Thrown by the siyuan.agent.registerCapability JS API exposed to plugins when fewer than 3 arguments are passed. The API contract requires exactly three arguments: a capability name string, a config object, and a handler function. goja reports call.Arguments as a sparse array padded with undefined, so len(call.Arguments) < 3 means the JS caller omitted at least one argument.

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 251596fc0d)

Solutions

  1. Provide all three arguments: name (string), config (object with description and inputSchema), handler (function)
  2. Check the plugin's registerCapability call site against the current API signature in api_agent.go

Example fix

// before
await siyuan.agent.registerCapability('myTool', {
  description: 'Does something',
  inputSchema: { type: 'object', properties: {} }
});

// after
await siyuan.agent.registerCapability('myTool', {
  description: 'Does something',
  inputSchema: { type: 'object', properties: {} }
}, (args) => {
  return { result: 'done' };
});
Defensive patterns

Strategy: try-catch

Validate before calling

if (arguments.length < 3) {
  throw new Error('registerCapability needs (name, config, handler)');
}
await siyuan.agent.registerCapability(name, config, handler);

Type guard

function isValidCapabilityCall(name, config, handler) {
  return typeof name === 'string' && name.trim() !== ''
    && config !== null && config !== undefined
    && typeof handler === 'function';
}

Try / catch

try {
  await siyuan.agent.registerCapability(name, config, handler);
} catch (e) {
  console.error('registerCapability failed:', e.message);
}

Prevention

When it happens

Trigger: A plugin calls siyuan.agent.registerCapability('myTool', config) — omitting the handler. Or siyuan.agent.registerCapability(config, handler) — omitting the name. Any call with fewer than three positional arguments triggers this.

Common situations: Plugin developer forgets the handler argument; destructures or passes arguments dynamically and one is missing; copy-paste from an older API version that had fewer required arguments.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/ab43c454dc19fb87. Report an issue: GitHub.