{"record":{"id":"378051521a50f79a","repo":"siyuan-note/siyuan","slug":"capability-name-must-not-be-empty","errorCode":null,"errorMessage":"capability name must not be empty","messagePattern":"capability name must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_agent.go","lineNumber":76,"sourceCode":"\n\t\tvar name string\n\t\tvar title string\n\t\tvar description string\n\t\tvar effects *tools.ToolEffects\n\t\tvar actionEffects map[string]tools.ToolEffects\n\t\tvar inputSchema *tools.ToolSchema\n\t\tvar outputSchema *tools.ToolSchema\n\t\tvar handler goja.Callable\n\n\t\targErr := func() (err error) {\n\t\t\tif len(call.Arguments) < 3 {\n\t\t\t\terr = fmt.Errorf(\"registerCapability requires 3 arguments: name, config, handler\")\n\t\t\t\treturn\n\t\t\t} else {\n\t\t\t\tif s := call.Argument(0); goja.IsString(s) {\n\t\t\t\t\tname = strings.TrimSpace(s.String())\n\t\t\t\t\tif name == \"\" {\n\t\t\t\t\t\terr = fmt.Errorf(\"capability name must not be empty\")\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\terr = fmt.Errorf(\"first argument must be a tool name string\")\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif c := call.Argument(1); isJsValueNotNull(c) {\n\t\t\t\t\tconfigObj := c.ToObject(rt)\n\t\t\t\t\tif configObj != nil {\n\t\t\t\t\t\tif titleValue := configObj.Get(\"title\"); goja.IsString(titleValue) {\n\t\t\t\t\t\t\ttitle = titleValue.String()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif descriptionValue := configObj.Get(\"description\"); goja.IsString(descriptionValue) {\n\t\t\t\t\t\t\tdescription = strings.TrimSpace(descriptionValue.String())\n\t\t\t\t\t\t\tif description == \"\" {\n\t\t\t\t\t\t\t\terr = fmt.Errorf(\"config.description must not be empty\")\n\t\t\t\t\t\t\t\treturn","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_agent.go#L58-L94","documentation":"Thrown by siyuan.agent.registerCapability when the first argument is a string but trims to empty. The capability name is used to construct the model-facing tool name via pluginCapabilityModelName, which sanitizes and hashes it, so an empty name would produce an ambiguous tool identity.","triggerScenarios":"Calling registerCapability('', config, handler), or registerCapability('   ', config, handler) — strings that are empty or contain only whitespace after strings.TrimSpace.","commonSituations":"Plugin uses a variable for the capability name that was initialized but never assigned; a template/placeholder string was left in place; dynamic name generation produced an empty result.","solutions":["Pass a non-empty, descriptive capability name as the first argument","If the name is dynamically generated, validate it is non-empty before calling registerCapability"],"exampleFix":"// before\nawait siyuan.agent.registerCapability('', config, handler);\n\n// after\nawait siyuan.agent.registerCapability('summarize-note', config, handler);","handlingStrategy":"validation","validationCode":"if (typeof name !== 'string' || name.trim() === '') {\n  throw new Error('Capability name must be a non-empty string');\n}\nawait siyuan.agent.registerCapability(name, config, handler);","typeGuard":"function isValidCapabilityName(name) {\n  return typeof name === 'string' && name.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Use descriptive, non-empty capability names that describe the tool's purpose","Validate dynamically generated names before passing them to registerCapability"],"tags":["plugin","agent","capability","validation"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}