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

Thrown by siyuan.agent.registerCapability when config.description is either missing entirely (undefined) or present but not a string (e.g., a number or object). The code checks goja.IsString(descriptionValue) — if the value is not a string type, this branch fires.

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 {
								return

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Add a string-valued description field to the config object
  2. Ensure description is a JS string primitive, not a number, object, or null

Example fix

// before
await siyuan.agent.registerCapability('myTool', {
  inputSchema: { type: 'object' }
}, handler);

// after
await siyuan.agent.registerCapability('myTool', {
  description: 'Extracts key points from a document',
  inputSchema: { type: 'object' }
}, handler);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof config.description !== 'string') {
  throw new Error('config.description is required and must be a string');
}
await siyuan.agent.registerCapability(name, config, handler);

Type guard

function hasStringDescription(config) {
  return config != null && typeof config.description === 'string';
}

Prevention

When it happens

Trigger: Omitting description from the config object entirely: { inputSchema: {...} }. Or passing a non-string: { description: 42, inputSchema: {...} } or { description: null, inputSchema: {...} }.

Common situations: Plugin developer forgets the description field; uses a non-string type (number, boolean) by mistake; the config object is built dynamically and the description key was never set.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/d5642c47a7e7ba30. Report an issue: GitHub.