siyuan-note/siyuan · warning

validation exceeded

Error message

validation exceeded %s

What it means

Once a validation slot is acquired, validateResolved runs jsonschema.Validate in a goroutine and waits up to toolValidationTime (2 seconds) for it to finish. If validation does not complete within 2 seconds — pathological payloads near the size/complexity limits on a slow host — the wait is abandoned with this timeout and the validation result is discarded.

Solutions

  1. Retry with a smaller, simpler payload; split large arguments into multiple calls.
  2. Reduce nesting and node count of the value being validated.
  3. Simplify the tool's schema (fewer patternProperties/regex constraints) so validation is cheaper.
  4. Raise toolValidationTime in validation.go only if legitimate payloads genuinely need longer.

Example fix

// before
validateResolved(ctx, slots, schema, deeplyNested8MBValue) // Validate > 2s
// after
validateResolved(ctx, slots, schema, summarizedValue) // flattened, paginated value validates well under 2s
Defensive patterns

Strategy: retry

Validate before calling

const depth = v => typeof v === "object" && v !== null ? 1 + Math.max(0, ...Object.values(v).map(depth)) : 0;
if (depth(payload) > 100) throw new Error("payload too deeply nested for fast validation");

Try / catch

if err := validator.ValidateOutput(result); err != nil {
  if strings.Contains(err.Error(), "validation exceeded") {
    // simplify payload or retry with a smaller value
    return retryWithTruncatedPayload(result)
  }
  return err
}

Prevention

When it happens

Trigger: Validating an input or structured-output value whose complexity (up to 128 depth / 262144 nodes) makes jsonschema.Validate exceed 2 seconds; heavily loaded CPU; an adversarial payload crafted to stress the validator (billion-laughs-style nesting within limits).

Common situations: Stress tests with maximal-size payloads; production hosts under CPU starvation validating many large tool payloads; regex-heavy schema keywords evaluated against long strings.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

		return ctx.Err()
	case <-timer.C:
		return fmt.Errorf("validation did not start within %s", toolValidationTime)
	}

	result := make(chan error, 1)
	go func() {
		err := schema.Validate(value)
		<-validationSlots
		result <- err
	}()

	select {
	case err := <-result:
		return err
	case <-ctx.Done():
		return ctx.Err()
	case <-timer.C:
		return fmt.Errorf("validation exceeded %s", toolValidationTime)
	}
}

func validateJSONComplexity(value any, maxDepth, maxNodes int) error {
	nodes := 0
	var walk func(any, int) error
	walk = func(current any, depth int) error {
		if depth > maxDepth {
			return fmt.Errorf("JSON depth exceeds %d", maxDepth)
		}
		nodes++
		if nodes > maxNodes {
			return fmt.Errorf("JSON node count exceeds %d", maxNodes)
		}
		switch typed := current.(type) {
		case map[string]any:
			for _, child := range typed {
				if err := walk(child, depth+1); err != nil {

View on GitHub (pinned to 9f775e8a12)