siyuan-note/siyuan · error
config.description is required and must be a string
Error message
config.description is required and must be a string
What it means
The config object passed to registerCapability() did not include a description property that is a string (it was missing, undefined, null, or a non-string type). The API requires description to be a string since it is surfaced to the agent runtime.
Solutions
- Add a non-empty string description to the config object
- Verify the key is spelled exactly description
- Ensure the value is a string, not a number, boolean, or object
Example fix
// before
plugin.registerCapability("search", { title: "Search", inputSchema }, handler);
// after
plugin.registerCapability("search", { title: "Search", description: "Search notes by keyword", inputSchema }, handler); Defensive patterns
Strategy: validation
Validate before calling
if (typeof config?.description !== "string") { throw new Error("config.description must be a string"); } Type guard
const hasStringDescription = (c) => c != null && typeof c.description === "string";
Try / catch
try { plugin.registerCapability(name, config, handler); } catch (e) { if (String(e).includes("config.description is required")) { console.error("Add description to capability config for", name); } throw e; } Prevention
- Spell the key exactly as description (not desc)
- Include description in every config template/boilerplate
- Validate the full config shape before registration
When it happens
Trigger: registerCapability(name, { title: "My tool", inputSchema }, handler) with description omitted entirely, or description: 123 / description: null.
Common situations: Older plugin code written before description became mandatory; configs built programmatically where the description key was never assigned; renamed key (e.g. desc) that the API does not read.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- config.description must not be empty
- config.inputSchema is required
- capability name must not be empty
- Conf.Language(123)
- Conf.Language(194)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/d5642c47a7e7ba30.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/api_agent.go:97
} 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
}
if inputSchemaValue := configObj.Get("inputSchema"); isJsValueNotNull(inputSchemaValue) {
if inputSchema, err = jsCapabilitySchemaToGoSchema(rt, inputSchemaValue); err != nil {
return
}
} else {
err = fmt.Errorf("config.inputSchema is required")
return
}
if outputSchemaValue := configObj.Get("outputSchema"); isJsValueNotNull(outputSchemaValue) {
if outputSchema, err = jsCapabilitySchemaToGoSchema(rt, outputSchemaValue); err != nil {
return
}
}
if effectsValue := configObj.Get("effects"); isJsValueNotNull(effectsValue) {
if effects, err = jsCapabilityEffectsToGoEffects(rt, effectsValue); err != nil {
returnView on GitHub (pinned to 9f775e8a12)