ComposioHQ/composio · error · RangeError

JSON Schema exceeds maximum nesting depth of ${MAX_NODE_DEPT

Error message

JSON Schema exceeds maximum nesting depth of ${MAX_NODE_DEPTH}

What it means

ensureObjectTypeOnProperties walks the schema to normalize properties and throws RangeError when nesting depth exceeds MAX_NODE_DEPTH, protecting against stack overflow on pathological inputs.

Source

Thrown at ts/packages/core/src/utils/jsonSchema.ts:304

}

/**
 * Returns a deep-cloned JSON Schema in which every node that carries a
 * `properties` keyword also carries `type: "object"` when it has no explicit
 * `type`. OpenAI tolerates the omission, but Google Gemini enforces OpenAPI
 * 3.0 strictly and rejects function declarations whose nested objects are
 * missing the `type` (see https://github.com/ComposioHQ/composio/issues/4022).
 *
 * The function follows JSON Schema's schema-bearing keywords while keeping
 * property maps and instance values as containers. Nodes that already declare
 * a `type` are left untouched.
 */
export function ensureObjectTypeOnProperties<T = unknown>(schema: T): T {
  type WalkMode = 'schema' | 'schema-array' | 'schema-map' | 'dependencies-map' | 'value';

  function walk(value: unknown, mode: WalkMode, depth = 0): unknown {
    if (depth > MAX_NODE_DEPTH) {
      throw new RangeError(`JSON Schema exceeds maximum nesting depth of ${MAX_NODE_DEPTH}`);
    }

    if (Array.isArray(value)) {
      const itemMode = mode === 'schema-array' ? 'schema' : 'value';
      return value.map(item => walk(item, itemMode, depth + 1));
    }

    if (!isPlainObject(value)) return value;

    const clone: Record<string, unknown> = {};
    for (const [key, child] of Object.entries(value)) {
      let childMode: WalkMode = 'value';
      if (mode === 'schema-map') {
        childMode = 'schema';
      } else if (mode === 'dependencies-map') {
        childMode = Array.isArray(child) ? 'value' : 'schema';
      } else if (mode === 'schema') {
        if (SCHEMA_MAP_KEYWORDS.has(key)) {

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Reduce schema nesting; collapse unnecessary intermediate levels.
  2. If the schema is user-supplied, validate its depth before registering the tool.
  3. Report tool definitions that legitimately need extreme depth to the SDK maintainers.
Defensive patterns

Strategy: validation

Validate before calling

const depth = (v: unknown, d = 0): number =>
  v && typeof v === 'object' ? Math.max(d, ...Object.values(v).map(x => depth(x, d + 1))) : d;
if (depth(schema) > 100) throw new Error('schema too deep');

Prevention

When it happens

Trigger: A schema with deeply nested arrays/maps/objects passed through tool parameter normalization (e.g. nested schema-array or dependencies-map modes) deeper than the cap.

Common situations: Recursive or machine-generated schemas; user-supplied tool definitions with unbounded self-referencing structures that escaped cycle detection.

Related errors


AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28). Data as JSON: /api/errors/c6b73ece9db5b512. Report an issue: GitHub.