siyuan-note/siyuan · error

first argument must be a tool name string

Error message

first argument must be a tool name string

What it means

Thrown by siyuan.agent.registerCapability when call.Argument(0) fails goja.IsString — the first argument exists but is not a JS string (e.g., a number, object, boolean, or symbol). The capability name must be a string because it is used to build the tool's internal identifier.

Source

Thrown at kernel/plugin/api_agent.go:80

		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()
						}
						if descriptionValue := configObj.Get("description"); goja.IsString(descriptionValue) {
							description = strings.TrimSpace(descriptionValue.String())
							if description == "" {
								err = fmt.Errorf("config.description must not be empty")
								return
							}
						} else {
							err = fmt.Errorf("config.description is required and must be a string")
							return

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Ensure the first argument is a string literal or a variable known to hold a string
  2. Use String(name) coercion if the value might be non-string, or validate with typeof name === 'string' before calling

Example fix

// before
await siyuan.agent.registerCapability({ name: 'myTool' }, config, handler);

// after
await siyuan.agent.registerCapability('myTool', config, handler);
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof name !== 'string') {
  throw new TypeError('Capability name must be a string');
}
await siyuan.agent.registerCapability(name, config, handler);

Type guard

function isStringArg(v) {
  return typeof v === 'string';
}

Prevention

When it happens

Trigger: Passing a number (registerCapability(42, ...)), an object (registerCapability({name: 'x'}, ...)), or undefined/null as the first argument. In goja, passing undefined explicitly is not a string.

Common situations: Plugin passes a configuration object first by mistake; uses a numeric ID instead of a string name; the first argument comes from an untyped source (JSON.parse result with unexpected types).

Related errors


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