{"record":{"id":"51b1bdabc89100c6","repo":"siyuan-note/siyuan","slug":"structured-content-is-required-when-an-output-sche","errorCode":null,"errorMessage":"structured content is required when an output schema is defined","messagePattern":"structured content is required when an output schema is defined","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/tools/validation.go","lineNumber":127,"sourceCode":"\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}\n\nfunc (validator *ToolValidator) ValidateOutput(result CallToolResult) error {\n\treturn validator.ValidateOutputContext(context.Background(), result)\n}\n\nfunc (validator *ToolValidator) ValidateOutputContext(ctx context.Context, result CallToolResult) error {\n\tif validator == nil || validator.output == nil || result.IsError {\n\t\treturn nil\n\t}\n\tif !result.HasStructuredContent() {\n\t\treturn fmt.Errorf(\"structured content is required when an output schema is defined\")\n\t}\n\tvalue, err := prepareValidationValue(result.StructuredContent)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"prepare structured content: %w\", err)\n\t}\n\treturn validateResolved(ctx, validator.validationSlots, validator.output, value)\n}\n\nfunc prepareValidationValue(value any) (any, error) {\n\tif err := validateJSONComplexity(value, maxToolValueDepth, maxToolValueNodes); err != nil {\n\t\treturn nil, err\n\t}\n\tdata, err := json.Marshal(value)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(data) > maxToolValueBytes {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mcp/tools/validation.go#L109-L145","documentation":"When a tool declares an OutputSchema, every successful CallToolResult (IsError=false) validated by ValidateOutputContext must carry structured content. This error is thrown if the result has no structured content, because there is nothing to validate against the output schema — the MCP contract requires structuredContent whenever an output schema is defined.","triggerScenarios":"A tool handler registered with a non-nil OutputSchema returns CallToolResult with only Content (text items) and no StructuredContent field set, and the result passes through ValidateOutputContext (e.g. via handleBrowserCapability or ValidateOutput).","commonSituations":"Adding an OutputSchema to an existing tool but forgetting to update its handler to populate StructuredContent; a code path returning early with a text-only result; refactoring a handler that used to be text-only into a structured-output tool.","solutions":["Populate result.StructuredContent with a value matching the tool's OutputSchema in every non-error return path.","If the tool cannot guarantee structured output, remove the OutputSchema declaration so validation is skipped.","Audit all return statements in the handler for the structured-content field.","Add a test that runs the compiled validator's ValidateOutput against representative handler results."],"exampleFix":"// before\nreturn CallToolResult{Content: []ContentItem{{Type: \"text\", Text: \"done\"}}}, nil\n// after\nreturn CallToolResult{Content: []ContentItem{{Type: \"text\", Text: \"done\"}}, StructuredContent: map[string]any{\"ok\": true}}, nil","handlingStrategy":"validation","validationCode":"function assertStructured(result) {\n  if (result.structuredContent === undefined) {\n    throw new Error(\"handler returned no structuredContent but OutputSchema is declared\");\n  }\n}","typeGuard":"func (r CallToolResult) hasStructured() bool { return r.StructuredContent != nil }","tryCatchPattern":"if err := validator.ValidateOutput(result); err != nil {\n  if strings.Contains(err.Error(), \"structured content is required\") {\n    // handler bug: populate StructuredContent or drop OutputSchema\n  }\n  return err\n}","preventionTips":["Populate StructuredContent in every non-error return path of tools that declare OutputSchema.","Search handler code paths for early returns that build text-only results.","Add validator-based tests over representative handler outputs.","Do not add OutputSchema to legacy text-only tools without updating the handler."],"tags":["mcp","structured-content","validation"],"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"}