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
- Reduce schema nesting; collapse unnecessary intermediate levels.
- If the schema is user-supplied, validate its depth before registering the tool.
- 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
- Flatten generated schemas.
- Treat depth-cap RangeErrors as schema-authoring bugs to fix upstream.
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
- JSON Schema node depth exceeded cap (${MAX_NODE_DEPTH})
- JSON Schema $ref chain exceeded depth cap (${MAX_REF_CHAIN_D
- Tool arguments exceed maximum nesting depth of ${MAX_NODE_DE
- JSON Schema node depth exceeded cap ({MAX_NODE_DEPTH})
- JSON Schema $ref chain exceeded depth cap ({MAX_REF_CHAIN_DE
AI-assisted analysis of ComposioHQ/composio@64b1b85502 (2026-08-28).
Data as JSON: /api/errors/c6b73ece9db5b512.
Report an issue: GitHub.