siyuan-note/siyuan · error
config.inputSchema is required
Error message
config.inputSchema is required
What it means
The config object did not include an inputSchema property (it was missing, undefined, or null). inputSchema is required because it defines the JSON Schema of the arguments the agent will pass to the capability handler; without it the kernel cannot validate or describe the tool's inputs.
Solutions
- Add an inputSchema JSON-Schema object describing the handler's arguments (e.g. { type: "object", properties: {...} })
- Use a minimal { type: "object" } schema if the tool takes no arguments
- Check that inputSchema is not set to null
Example fix
// before
plugin.registerCapability("search", { description: "Search notes" }, handler);
// after
plugin.registerCapability("search", { description: "Search notes", inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] } }, handler); Defensive patterns
Strategy: validation
Validate before calling
if (!config?.inputSchema || config.inputSchema === null) { throw new Error("config.inputSchema is required"); } Type guard
const hasInputSchema = (c) => c != null && c.inputSchema != null && typeof c.inputSchema === "object";
Try / catch
try { plugin.registerCapability(name, config, handler); } catch (e) { if (String(e).includes("config.inputSchema is required")) { config.inputSchema = { type: "object" }; return plugin.registerCapability(name, config, handler); } throw e; } Prevention
- Always declare an inputSchema, even a minimal { type: "object" } for no-arg tools
- Model schemas after the plugin samples
- Note outputSchema is optional but inputSchema is not
When it happens
Trigger: registerCapability(name, { description: "..." }, handler) with inputSchema omitted, or inputSchema explicitly set to null.
Common situations: Migrating from an older registration API that had no schema requirement; configs shared between plugins where the schema section was dropped; assuming inputSchema is optional like outputSchema.
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 is required and must be a string
- attribute view embedded base is missing
- capability name must not be empty
- config.description must not be empty
- event.data is required
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/6de4ac942c643e0e.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/plugin/api_agent.go:105
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
}
}
if actionEffectsValue := configObj.Get("actionEffects"); isJsValueNotNull(actionEffectsValue) {
if actionEffects, err = jsCapabilityActionEffectsToGoEffects(rt, actionEffectsValue); err != nil {
return
}
}
}View on GitHub (pinned to 9f775e8a12)