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

The first argument to registerCapability() was not a string. The runtime checks goja.IsString on argument 0 and rejects any non-string type (number, object, undefined, null, boolean). Capability names must be strings because they become tool identifiers.

Solutions

  1. Ensure the first argument is a plain string tool name
  2. Reorder arguments to (name, config, handler) if they were swapped
  3. Coerce or validate the name with typeof name === "string" before calling

Example fix

// before
plugin.registerCapability(config, handler);
// after
plugin.registerCapability("myplugin_tool", config, handler);
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof name !== "string") { throw new TypeError("capability name must be a string, got " + typeof name); }

Type guard

const isName = (v) => typeof v === "string";

Try / catch

try { plugin.registerCapability(name, config, handler); } catch (e) { if (String(e).includes("first argument must be a tool name string")) { throw new TypeError("Fix argument order: (name, config, handler)"); } throw e; }

Prevention

When it happens

Trigger: registerCapability(123, config, handler), passing an options object as the first argument (registerCapability(config, handler)), or a variable holding undefined/null because an earlier lookup failed.

Common situations: Swapped argument order — developers often pass config first; a name constant imported from a module that is actually an object; JSON-driven plugin config where the name field is missing so the lookup yields undefined.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/9288109a9031a0c0. Report an issue: GitHub.

Appendix: 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 9f775e8a12)