{"record":{"id":"4bf5cb704d879f99","repo":"siyuan-note/siyuan","slug":"failed-to-serialize-inputschema-v","errorCode":null,"errorMessage":"failed to serialize inputSchema: %v","messagePattern":"failed to serialize inputSchema: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_agent.go","lineNumber":263,"sourceCode":"\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.agent.unregisterCapability worker run: %v\", p.Name, runErr)\n\t\t\tif rejectErr := reject(rt.NewGoError(runErr)); rejectErr != nil {\n\t\t\t\tlogging.LogErrorf(\"[plugin:%s] siyuan.agent.unregisterCapability reject on run error: %v\", p.Name, rejectErr)\n\t\t\t}\n\t\t}\n\n\t\treturn rt.ToValue(promise)\n\t})))\n\n\tlo.Must0(ObjectFreeze(rt, agentAPI))\n\tlo.Must0(siyuan.Set(\"agent\", agentAPI))\n\treturn\n}\n\n// jsCapabilitySchemaToGoSchema 将 JavaScript 能力 Schema 转换为 Go ToolSchema。\nfunc jsCapabilitySchemaToGoSchema(rt *goja.Runtime, value goja.Value) (toolSchema *tools.ToolSchema, err error) {\n\tschemaJson, marshalErr := value.ToObject(rt).MarshalJSON()\n\tif marshalErr != nil {\n\t\terr = fmt.Errorf(\"failed to serialize inputSchema: %v\", marshalErr)\n\t\treturn\n\t}\n\n\tschema := &tools.ToolSchema{}\n\tunmarshalErr := json.Unmarshal(schemaJson, schema)\n\tif unmarshalErr != nil {\n\t\terr = fmt.Errorf(\"invalid json schema: %v\", unmarshalErr)\n\t\treturn\n\t}\n\n\ttoolSchema = schema\n\treturn\n}\n\nfunc jsCapabilityEffectsToGoEffects(rt *goja.Runtime, value goja.Value) (*tools.ToolEffects, error) {\n\teffects := &tools.ToolEffects{}\n\tif err := unmarshalCapabilityJSON(rt, value, effects, \"effects\"); err != nil {\n\t\treturn nil, err","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/api_agent.go#L245-L281","documentation":"Thrown by jsCapabilitySchemaToGoSchema when value.ToObject(rt).MarshalJSON() fails. This converts the JS inputSchema (or outputSchema) value to JSON for unmarshaling into the Go tools.ToolSchema struct. MarshalJSON fails when the value contains non-serializable content such as circular references, functions, or symbols.","triggerScenarios":"Passing an inputSchema that contains function values, circular references, or goja-specific non-serializable objects. For example, inputSchema = { type: 'object', validate: () => true } where 'validate' is a function that cannot be JSON-serialized.","commonSituations":"Plugin includes validator functions or computed getters in the schema object; the schema references itself; a prototype pollution or incorrect object construction introduces non-serializable members.","solutions":["Ensure the inputSchema is a plain JSON-serializable object — no functions, symbols, or circular references","Use JSON.parse(JSON.stringify(schema)) before passing to strip non-serializable properties","If using a schema builder library, call its .toJSON() or equivalent to get a plain object"],"exampleFix":"// before\nawait siyuan.agent.registerCapability('myTool', {\n  description: '...',\n  inputSchema: {\n    type: 'object',\n    validate: (val) => val > 0  // function — not serializable\n  }\n}, handler);\n\n// after\nawait siyuan.agent.registerCapability('myTool', {\n  description: '...',\n  inputSchema: {\n    type: 'object',\n    properties: {\n      val: { type: 'number', minimum: 1 }\n    }\n  }\n}, handler);","handlingStrategy":"validation","validationCode":"// Strip non-serializable properties before passing\nconst cleanSchema = JSON.parse(JSON.stringify(inputSchema));\nif (!cleanSchema) {\n  throw new Error('inputSchema must be JSON-serializable');\n}\nconfig.inputSchema = cleanSchema;\nawait siyuan.agent.registerCapability(name, config, handler);","typeGuard":"function isJsonSerializable(obj) {\n  try {\n    JSON.stringify(obj);\n    return true;\n  } catch {\n    return false;\n  }\n}","tryCatchPattern":"try {\n  await siyuan.agent.registerCapability(name, config, handler);\n} catch (e) {\n  if (e.message.includes('serialize inputSchema')) {\n    // schema has non-serializable content — strip and retry\n    config.inputSchema = JSON.parse(JSON.stringify(config.inputSchema));\n  }\n}","preventionTips":["Build schemas from plain data objects, not class instances with methods","Run JSON.parse(JSON.stringify(schema)) as a sanitization step before passing schemas"],"tags":["plugin","agent","capability","schema","serialization","javascript"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}