ComposioHQ/composio · error · Error

Tool schema nesting exceeded the maximum supported depth (${

Error message

Tool schema nesting exceeded the maximum supported depth (${MAX_SCHEMA_DEPTH})

What it means

The SDK renames tool-schema property keys that collide with dangerous prototypes, and recursively sanitizes the schema with a hard depth cap (MAX_SCHEMA_DEPTH). sanitizeNode throws when the tool's JSON schema nests deeper than that cap, protecting against cyclic or pathological schemas.

Source

Thrown at ts/packages/core/src/utils/schemaPropertyKeys.ts:219

 * Recursively sanitizes the property keys of a JSON-schema node, returning the
 * rewritten node and a {@link KeyMapping} shaped like the node. Traversal covers
 * object `properties`, array `items`/`prefixItems`, the composition keywords
 * (`allOf`/`anyOf`/`oneOf`, `not`/`if`/`then`/`else` — whose renames merge into
 * this level), and the rewrite-only positions in {@link REWRITE_ONLY_SINGLE_KEYWORDS}
 * / {@link REWRITE_ONLY_MAP_KEYWORDS}.
 *
 * The input node is never mutated; a new node is returned.
 */
function sanitizeNode(
  node: Record<string, unknown>,
  policy: KeySanitizationPolicy,
  depth = 0
): {
  node: Record<string, unknown>;
  mapping: KeyMapping;
} {
  if (depth >= MAX_SCHEMA_DEPTH) {
    throw new Error(
      `Tool schema nesting exceeded the maximum supported depth (${MAX_SCHEMA_DEPTH})`
    );
  }

  const result: Record<string, unknown> = { ...node };
  // Lookup/result tables are prototype-free so a property key that collides with
  // an `Object.prototype` member (`__proto__`, `constructor`, `toString`, …)
  // becomes a plain own entry instead of resolving to (or reparenting via) the
  // inherited member. Mirrors the `POLLUTING_KEYS` defense in `jsonSchema.ts`.
  const renames: Record<string, string> = Object.create(null);
  const children: Record<string, KeyMapping> = Object.create(null);
  const mapping: KeyMapping = { renames, children };

  const properties = node.properties;
  if (isPlainObject(properties)) {
    const newProperties: Record<string, unknown> = Object.create(null);
    const renamedOriginalToSanitized: Record<string, string> = Object.create(null);

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Inspect the failing tool's schema and flatten or remove unnecessary nesting
  2. If the schema is recursive, express it with $defs/$ref instead of inline expansion so the physical nesting is shallow
  3. Reduce nesting in the tool's parameter type definition before registering the tool
  4. Report the tool/schema to Composio if it's a built-in integration tool you can't modify
Defensive patterns

Strategy: validation

Validate before calling

const schemaDepth = (s: object, d = 0): number =>
  d > 20 ? d : Math.max(d, ...Object.values(s)
    .filter(v => v && typeof v === 'object')
    .map(v => schemaDepth(v as object, d + 1)));
if (schemaDepth(toolSchema) >= MAX_SCHEMA_DEPTH) throw new Error('schema too deep');

Type guard

null

Try / catch

try {
  await composio.tools.execute(action, args);
} catch (e) {
  if (e instanceof Error && e.message.includes('nesting exceeded the maximum supported depth')) {
    // flatten or fix the tool schema
  }
}

Prevention

When it happens

Trigger: Registering or executing a tool whose parameter JSON schema (nested objects/arrays/allOf etc.) exceeds MAX_SCHEMA_DEPTH — often a schema with an accidental self-referencing $ref-like cycle, or a generated schema with extremely deep nesting.

Common situations: Auto-generated OpenAPI/JSON schemas with recursive models expanded inline; deeply nested config types from codegen; a tool definition accidentally embedding itself.

Related errors


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