siyuan-note/siyuan · error

invalid json schema: %v

Error message

invalid json schema: %v

What it means

Thrown by jsCapabilitySchemaToGoSchema when the JSON-serialized schema fails to unmarshal into the Go tools.ToolSchema struct. The JSON is valid (MarshalJSON succeeded) but its structure does not match the ToolSchema Go type — missing required fields, wrong types, or unknown enum values.

Source

Thrown at kernel/plugin/api_agent.go:270

	})))

	lo.Must0(ObjectFreeze(rt, agentAPI))
	lo.Must0(siyuan.Set("agent", agentAPI))
	return
}

// jsCapabilitySchemaToGoSchema 将 JavaScript 能力 Schema 转换为 Go ToolSchema。
func jsCapabilitySchemaToGoSchema(rt *goja.Runtime, value goja.Value) (toolSchema *tools.ToolSchema, err error) {
	schemaJson, marshalErr := value.ToObject(rt).MarshalJSON()
	if marshalErr != nil {
		err = fmt.Errorf("failed to serialize inputSchema: %v", marshalErr)
		return
	}

	schema := &tools.ToolSchema{}
	unmarshalErr := json.Unmarshal(schemaJson, schema)
	if unmarshalErr != nil {
		err = fmt.Errorf("invalid json schema: %v", unmarshalErr)
		return
	}

	toolSchema = schema
	return
}

func jsCapabilityEffectsToGoEffects(rt *goja.Runtime, value goja.Value) (*tools.ToolEffects, error) {
	effects := &tools.ToolEffects{}
	if err := unmarshalCapabilityJSON(rt, value, effects, "effects"); err != nil {
		return nil, err
	}
	return effects, nil
}

func jsCapabilityActionEffectsToGoEffects(rt *goja.Runtime, value goja.Value) (map[string]tools.ToolEffects, error) {
	actionEffects := map[string]tools.ToolEffects{}
	if err := unmarshalCapabilityJSON(rt, value, &actionEffects, "actionEffects"); err != nil {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Ensure inputSchema follows standard JSON Schema format with 'type', 'properties', etc.
  2. Validate the schema against the tools.ToolSchema struct definition in kernel/mcp/tools
  3. Use a JSON Schema validator library on the JS side before passing the schema

Example fix

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

// after
await siyuan.agent.registerCapability('myTool', {
  description: '...',
  inputSchema: {
    type: 'object',
    properties: {
      query: { type: 'string' }
    }
  }
}, handler);
Defensive patterns

Strategy: validation

Validate before calling

// Validate schema is a plain object with expected JSON Schema structure
if (typeof inputSchema !== 'object' || Array.isArray(inputSchema)) {
  throw new Error('inputSchema must be a JSON Schema object');
}
if (typeof inputSchema.type !== 'string') {
  throw new Error('inputSchema.type must be a string (e.g., "object")');
}
config.inputSchema = inputSchema;

Type guard

function isValidJsonSchema(v) {
  return v != null && typeof v === 'object'
    && !Array.isArray(v)
    && typeof v.type === 'string';
}

Prevention

When it happens

Trigger: Passing an inputSchema whose JSON structure doesn't match tools.ToolSchema — for example, an array instead of an object, or an object with type: 'invalid' where the Go struct expects a specific set of values.

Common situations: Plugin uses an ad-hoc schema format instead of standard JSON Schema; the schema was hand-written with typos; a version change in the ToolSchema struct introduced new required fields.

Understand the failure class

Related errors


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