{"record":{"id":"9288109a9031a0c0","repo":"siyuan-note/siyuan","slug":"first-argument-must-be-a-tool-name-string","errorCode":null,"errorMessage":"first argument must be a tool name string","messagePattern":"first argument must be a tool name string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_agent.go","lineNumber":80,"sourceCode":"\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\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\terr = fmt.Errorf(\"config.description is required and must be a string\")\n\t\t\t\t\t\t\treturn","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_agent.go#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Ensure the first argument is a string literal or a variable known to hold a string","Use String(name) coercion if the value might be non-string, or validate with typeof name === 'string' before calling"],"exampleFix":"// before\nawait siyuan.agent.registerCapability({ name: 'myTool' }, config, handler);\n\n// after\nawait siyuan.agent.registerCapability('myTool', config, handler);","handlingStrategy":"type-guard","validationCode":"if (typeof name !== 'string') {\n  throw new TypeError('Capability name must be a string');\n}\nawait siyuan.agent.registerCapability(name, config, handler);","typeGuard":"function isStringArg(v) {\n  return typeof v === 'string';\n}","tryCatchPattern":null,"preventionTips":["Pass string literals or verified string variables as the capability name","Coerce with String(name) only if you are certain the value is meaningfully string-like"],"tags":["plugin","agent","capability","type-mismatch","javascript"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}