ComposioHQ/composio · error · JsonSchemaRefResolutionError

JSON Schema node depth exceeded cap (${MAX_NODE_DEPTH})

Error message

JSON Schema node depth exceeded cap (${MAX_NODE_DEPTH})

What it means

walk(), which clones/dereferences schemas, caps total node depth at MAX_NODE_DEPTH to prevent stack exhaustion from deeply nested schemas. Reaching the cap throws JsonSchemaRefResolutionError with suggested fixes.

Source

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

    visitedRefs: ReadonlySet<string>,
    chainDepth: number,
    nodeDepth: number
  ): Record<string, unknown> =>
    Object.fromEntries(
      Object.entries(obj)
        .filter(([k]) => !POLLUTING_KEYS.has(k))
        .map(([k, v]) => [k, walk(v, visitedRefs, chainDepth, nodeDepth + 1)])
    );

  // `function` (not `const`) so `cloneChildren` above can call it via hoisting.
  function walk(
    node: unknown,
    visitedRefs: ReadonlySet<string>,
    chainDepth: number,
    nodeDepth: number
  ): unknown {
    if (nodeDepth >= MAX_NODE_DEPTH) {
      throw new JsonSchemaRefResolutionError(
        `JSON Schema node depth exceeded cap (${MAX_NODE_DEPTH})`,
        { possibleFixes: REF_RESOLUTION_FIXES }
      );
    }
    if (Array.isArray(node)) {
      if (visiting.has(node)) return { ...CYCLE_BREAK_SENTINEL };
      visiting.add(node);
      try {
        return node.map(item => walk(item, visitedRefs, chainDepth, nodeDepth + 1));
      } finally {
        visiting.delete(node);
      }
    }
    if (!isPlainObject(node)) return node;
    if (visiting.has(node)) return { ...CYCLE_BREAK_SENTINEL };
    visiting.add(node);
    try {
      const ref = typeof node.$ref === 'string' ? node.$ref : null;

View on GitHub (pinned to 64b1b85502)

Solutions

  1. Flatten or simplify the schema; remove needless wrapper objects.
  2. If the schema comes from a tool definition you control, bound recursion when generating it.
  3. Do not feed untrusted schemas directly; pre-validate depth before calling SDK APIs.
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;

Prevention

When it happens

Trigger: Passing a tool schema with extremely deep property nesting (thousands of levels), sometimes generated programmatically or via recursive allOf/property chains.

Common situations: Machine-generated schemas (e.g. from recursive TypeScript types) or adversarial/malformed schemas from untrusted tool sources.

Related errors


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