siyuan-note/siyuan · error

prepare structured content

Error message

prepare structured content: %w

What it means

ValidateOutputContext normalizes the result's StructuredContent via prepareValidationValue before schema validation (JSON round-trip for canonicalization plus complexity checks). If that preparation fails — unmarshalable value, size over maxToolValueBytes (8 MiB), or depth/node limits (128 depth, 262144 nodes) — the error is wrapped as 'prepare structured content: ...'.

Solutions

  1. Read the wrapped inner error: json marshal error, byte limit, or complexity limit — fix accordingly.
  2. Ensure StructuredContent only contains JSON-safe types (maps, slices, strings, numbers, bools, nil).
  3. Trim or reference (e.g. by asset path) large payloads instead of embedding them in structured content.
  4. Flatten deep nesting in the handler's output value.

Example fix

// before
StructuredContent: map[string]any{"blob": someChannel} // json.Marshal fails
// after
StructuredContent: map[string]any{"blobId": blobID} // pass an identifier, keep value JSON-safe
Defensive patterns

Strategy: validation

Validate before calling

const encoded = JSON.stringify(result.structuredContent);
if (encoded.length > 8 * 1024 * 1024) throw new Error("structured content exceeds 8 MiB");

Type guard

function isJSONSafe(v, seen = new Set()) {
  if (v === null || ["string","number","boolean"].includes(typeof v)) return true;
  if (typeof v !== "object" || seen.has(v)) return false;
  seen.add(v);
  return Object.values(v).every(x => isJSONSafe(x, seen));
}

Try / catch

if err := validator.ValidateOutputContext(ctx, result); err != nil {
  var pe *json.UnsupportedTypeError // or inspect wrapped 'prepare structured content' error
  if strings.HasPrefix(err.Error(), "prepare structured content:") {
    return fmt.Errorf("handler emitted non-serializable or oversized output: %w", err)
  }
  return err
}

Prevention

When it happens

Trigger: A tool result's StructuredContent contains values json.Marshal cannot encode (channels, funcs, cyclic maps), exceeds 8 MiB serialized, or nests deeper than 128 levels / has more than 262144 nodes.

Common situations: Returning Go structs with unsupported field types in StructuredContent; accidentally including huge blobs (base64 file contents) in structured output; deeply recursive data structures produced by the handler.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

	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 {
		return nil, fmt.Errorf("value exceeds %d bytes", maxToolValueBytes)
	}
	var canonical any
	if err = json.Unmarshal(data, &canonical); err != nil {

View on GitHub (pinned to 9f775e8a12)