danny-avila/LibreChat · error · AgentRunEnvelopeError

${path} exceeds the maximum nesting depth of ${AGENT_RUN_ENV

Error message

${path} exceeds the maximum nesting depth of ${AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH}

What it means

cloneJsonValue walks the payload recursively to deep-clone it for the transport-safe envelope. If nesting exceeds AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH (64), it throws AgentRunEnvelopeError. The cap prevents stack overflow and rejects pathological/deeply nested payloads that should not cross the execution seam.

Source

Thrown at packages/api/src/agents/envelope.ts:102

  }
}

function assertNonEmptyString(value: string | undefined, path: string): string {
  if (typeof value !== 'string' || value.trim().length === 0) {
    throw new AgentRunEnvelopeError(`${path} must be a non-empty string`);
  }
  return value;
}

function cloneJsonValue<T>(value: T, path: string, ancestors: WeakSet<object>, depth: number): T;
function cloneJsonValue(
  value: unknown,
  path: string,
  ancestors: WeakSet<object>,
  depth: number,
): unknown {
  if (depth > AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH) {
    throw new AgentRunEnvelopeError(
      `${path} exceeds the maximum nesting depth of ${AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH}`,
    );
  }

  if (value === null || typeof value === 'string' || typeof value === 'boolean') {
    return value;
  }

  if (typeof value === 'number') {
    if (!Number.isFinite(value)) {
      throw new AgentRunEnvelopeError(`${path} must contain only finite numbers`);
    }
    return value;
  }

  if (typeof value !== 'object') {
    throw new AgentRunEnvelopeError(`${path} contains a non-JSON ${typeof value} value`);
  }

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Flatten or summarize deeply nested tool results before placing them in the envelope payload.
  2. Validate max depth of tool outputs at the tool boundary, not at envelope construction.
  3. If 64 is too low for a legitimate use case, raise AGENT_RUN_ENVELOPE_MAX_NESTING_DEPTH only after confirming stack safety.

Example fix

// before — tool returns a 100-deep tree, inlined into payload
payload.messages.push({ role: 'tool', content: JSON.stringify(deepTree) });

// after — summarize first
const summary = summarizeTree(deepTree, { maxDepth: 10 });
payload.messages.push({ role: 'tool', content: JSON.stringify(summary) });
Defensive patterns

Strategy: validation

Validate before calling

const MAX_DEPTH = 64;
function jsonDepth(v: unknown, d = 0): number {
  if (d > MAX_DEPTH) return d;
  if (Array.isArray(v)) return Math.max(...v.map((x) => jsonDepth(x, d + 1)), d);
  if (v && typeof v === 'object') return Math.max(...Object.values(v).map((x) => jsonDepth(x, d + 1)), d);
  return d;
}
if (jsonDepth(payload) > MAX_DEPTH) throw new Error('payload nests too deep');

Try / catch

import { AgentRunEnvelopeError } from '~/agents/envelope';
try {
  envelope = createAgentRunEnvelope(input);
} catch (error) {
  if (error instanceof AgentRunEnvelopeError && /nesting depth/.test(error.message)) {
    payload.messages = summarizeDeeplyNestedMessages(payload.messages);
    envelope = createAgentRunEnvelope(input); // retry once
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Passing a payload whose JSON nesting depth exceeds 64 levels — e.g. a tool result with deeply recursive structure, a document tree, or an accidentally self-referential object that bypassed the circular-reference check via different parents.

Common situations: A tool returning a deeply nested API response (e.g. a file-tree dump) inlined into the payload; serialization of ORM objects that nest relations; an adversarial or buggy MCP server emitting depth bombs.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/b3ac619ba253fa9b. Report an issue: GitHub.