siyuan-note/siyuan · error

structured content is required when an output schema is…

Error message

structured content is required when an output schema is defined

What it means

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.

Solutions

  1. Populate result.StructuredContent with a value matching the tool's OutputSchema in every non-error return path.
  2. If the tool cannot guarantee structured output, remove the OutputSchema declaration so validation is skipped.
  3. Audit all return statements in the handler for the structured-content field.
  4. Add a test that runs the compiled validator's ValidateOutput against representative handler results.

Example fix

// before
return CallToolResult{Content: []ContentItem{{Type: "text", Text: "done"}}}, nil
// after
return CallToolResult{Content: []ContentItem{{Type: "text", Text: "done"}}, StructuredContent: map[string]any{"ok": true}}, nil
Defensive patterns

Strategy: validation

Validate before calling

function assertStructured(result) {
  if (result.structuredContent === undefined) {
    throw new Error("handler returned no structuredContent but OutputSchema is declared");
  }
}

Type guard

func (r CallToolResult) hasStructured() bool { return r.StructuredContent != nil }

Try / catch

if err := validator.ValidateOutput(result); err != nil {
  if strings.Contains(err.Error(), "structured content is required") {
    // handler bug: populate StructuredContent or drop OutputSchema
  }
  return err
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/51b1bdabc89100c6. Report an issue: GitHub.

Appendix: source

Thrown at kernel/mcp/tools/validation.go:127

	if validator == nil || validator.input == nil {
		return nil
	}
	value, err := prepareValidationValue(arguments)
	if err != nil {
		return err
	}
	return validateResolved(ctx, validator.validationSlots, validator.input, value)
}

func (validator *ToolValidator) ValidateOutput(result CallToolResult) error {
	return validator.ValidateOutputContext(context.Background(), result)
}

func (validator *ToolValidator) ValidateOutputContext(ctx context.Context, result CallToolResult) error {
	if validator == nil || validator.output == nil || result.IsError {
		return nil
	}
	if !result.HasStructuredContent() {
		return fmt.Errorf("structured content is required when an output schema is defined")
	}
	value, err := prepareValidationValue(result.StructuredContent)
	if err != nil {
		return fmt.Errorf("prepare structured content: %w", err)
	}
	return validateResolved(ctx, validator.validationSlots, validator.output, value)
}

func prepareValidationValue(value any) (any, error) {
	if err := validateJSONComplexity(value, maxToolValueDepth, maxToolValueNodes); err != nil {
		return nil, err
	}
	data, err := json.Marshal(value)
	if err != nil {
		return nil, err
	}
	if len(data) > maxToolValueBytes {

View on GitHub (pinned to 9f775e8a12)