siyuan-note/siyuan · error

capability name must not be empty

Error message

capability name must not be empty

What it means

The first argument to registerCapability() was a string, but after trimming whitespace it was empty. Every capability must have a non-empty name so the kernel can key it, expose it to the agent, and allow later unregistration by name.

Solutions

  1. Provide a non-empty, trimmed name string as the first argument
  2. Check the variable feeding the name for empty/whitespace-only values before registering
  3. Use a stable, descriptive identifier (e.g. "myplugin_search_notes")

Example fix

// before
const name = "   ";
plugin.registerCapability(name, config, handler);
// after
const name = "myplugin_search_notes";
if (name.trim()) plugin.registerCapability(name, config, handler);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof name === "string" && name.trim() === "") { throw new Error("capability name is empty"); }

Type guard

const hasValidName = (n) => typeof n === "string" && n.trim().length > 0;

Try / catch

try { plugin.registerCapability(name, config, handler); } catch (e) { if (String(e).includes("name must not be empty")) { name = fallbackName; return plugin.registerCapability(name, config, handler); } throw e; }

Prevention

When it happens

Trigger: registerCapability("", config, handler), registerCapability(" ", config, handler), or passing a variable that resolves to an empty string (e.g. an unset constant or an object lookup that returned "").

Common situations: Template placeholders like registerCapability(TOOL_NAME, ...) where TOOL_NAME was never set; config-driven registration where the tool name field is empty; building names via concatenation where a prefix/suffix variable is blank.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at kernel/plugin/api_agent.go:76

		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()
						}
						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

View on GitHub (pinned to 9f775e8a12)