{"record":{"id":"bd418b044c39d9e2","repo":"siyuan-note/siyuan","slug":"root-type-must-be-object","errorCode":null,"errorMessage":"root type must be \"object\"","messagePattern":"root type must be \"object\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/tools/validation.go","lineNumber":99,"sourceCode":"\t}\n\tvar raw any\n\tif err = json.Unmarshal(data, &raw); err != nil {\n\t\treturn nil, err\n\t}\n\tif err = validateJSONComplexity(raw, maxToolSchemaDepth, maxToolSchemaNodes); err != nil {\n\t\treturn nil, err\n\t}\n\tif requireObject {\n\t\tif err = validateParamHeaderAnnotations(raw); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\tvar parsed jsonschema.Schema\n\tif err = json.Unmarshal(data, &parsed); err != nil {\n\t\treturn nil, err\n\t}\n\tif requireObject && parsed.Type != \"object\" {\n\t\treturn nil, fmt.Errorf(`root type must be \"object\"`)\n\t}\n\treturn parsed.Resolve(nil)\n}\n\nfunc (validator *ToolValidator) ValidateInput(arguments map[string]any) error {\n\treturn validator.ValidateInputContext(context.Background(), arguments)\n}\n\nfunc (validator *ToolValidator) ValidateInputContext(ctx context.Context, arguments map[string]any) error {\n\tif validator == nil || validator.input == nil {\n\t\treturn nil\n\t}\n\tvalue, err := prepareValidationValue(arguments)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn validateResolved(ctx, validator.validationSlots, validator.input, value)\n}","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/tools/validation.go#L81-L117","documentation":"MCP tool input schemas must describe an object of named arguments. When compiling an input schema (requireObject=true), resolveToolSchema checks the parsed schema's Type field and rejects any root that is not \"object\". Output schemas are exempt from this check.","triggerScenarios":"Registering a tool whose InputSchema.Type is missing, empty, or set to something other than \"object\" (e.g. \"string\", \"array\", or absent) — the schema unmarshals fine but fails the root-type gate in resolveToolSchema.","commonSituations":"Copy-pasting an output schema (which may have any root type) into the InputSchema slot; building ToolSchema programmatically and forgetting to set Type; simplifying a no-argument tool to Type:\"null\" or leaving it empty instead of an empty object schema.","solutions":["Set InputSchema.Type to \"object\"; for tools with no arguments use an object schema with no properties.","Verify the field is set on InputSchema (not only OutputSchema) when constructing ToolSchema manually.","Check the wrapped compile error — this message appears as the inner error of 'invalid input schema'.","Add a registration-time unit test calling CompileToolValidator for every tool."],"exampleFix":"// before\nInputSchema: ToolSchema{Properties: map[string]Property{...}} // Type unset\n// after\nInputSchema: ToolSchema{Type: \"object\", Properties: map[string]Property{...}}","handlingStrategy":"type-guard","validationCode":"if (tool.InputSchema?.type !== \"object\") {\n  throw new Error(\"tool input schema root must be of type object\");\n}","typeGuard":"func inputSchemaIsObject(t *Tool) bool {\n  return t != nil && t.InputSchema.Type == \"object\"\n}","tryCatchPattern":null,"preventionTips":["Always initialize InputSchema with Type: \"object\", even for zero-argument tools.","Do not reuse output schemas as input schemas — the root-type rule differs.","Lint tool declarations for missing Type fields before registration."],"tags":["mcp","json-schema","tools"],"backgroundTag":"schema-validation-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}