danny-avila/LibreChat · error · AgentRunEnvelopeError

${path} contains a circular reference

Error message

${path} contains a circular reference

What it means

Thrown by cloneJsonValue when an object inside the payload is revisited while still on its own ancestor chain (tracked via a WeakSet 'ancestors'). A self-referential or mutually-referential object graph cannot be serialized to JSON and would recurse forever, so the clone refuses it. The WeakSet is scoped per top-level clone and entries are deleted on the way back up, so a value appearing in two sibling branches is fine; only a true cycle trips this.

Source

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

  }

  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`);
  }

  if (ancestors.has(value)) {
    throw new AgentRunEnvelopeError(`${path} contains a circular reference`);
  }

  ancestors.add(value);

  try {
    const symbolKeys = Object.getOwnPropertySymbols(value);
    if (symbolKeys.length > 0) {
      throw new AgentRunEnvelopeError(`${path} contains symbol keys`);
    }

    if (Array.isArray(value)) {
      const cloned: unknown[] = new Array(value.length);
      let clonedItemCount = 0;
      for (const key of Object.getOwnPropertyNames(value)) {
        if (key === 'length') {
          continue;
        }
        const index = Number(key);

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Follow the path in the message to the first object that closes the cycle.
  2. Sever the back-reference (delete the parent pointer) or replace the cyclic structure with an acyclic, JSON-friendly shape (e.g. ids instead of object links).
  3. Run JSON.stringify(payload) locally before calling createAgentRunEnvelope; if it throws 'circular', fix the shape there first.

Example fix

// before
const node = { id: 1, label: 'root' };
node.parent = node;
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { tree: node } });

// after
const node = { id: 1, label: 'root', parentId: null };
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { tree: node } });
Defensive patterns

Strategy: validation

Validate before calling

function isAcyclic(value: unknown, seen = new WeakSet()): boolean {
  if (typeof value !== 'object' || value === null) return true;
  if (seen.has(value as object)) return false;
  seen.add(value as object);
  if (Array.isArray(value)) return (value as unknown[]).every((v) => isAcyclic(v, seen));
  return Object.values(value).every((v) => isAcyclic(v, seen));
}
if (!isAcyclic(payload)) throw new Error('payload contains a cycle');

Type guard

function isAcyclicJson(value: unknown, seen = new WeakSet()): boolean {
  if (value === null || typeof value !== 'object') return true;
  if (seen.has(value as object)) return false;
  seen.add(value as object);
  const vals = Array.isArray(value) ? value : Object.values(value);
  return vals.every((v) => isAcyclicJson(v, seen));
}

Try / catch

try {
  const env = createAgentRunEnvelope(input);
} catch (e) {
  if (e instanceof AgentRunEnvelopeError && /circular reference/.test(e.message)) {
    // the path names the cycle origin; sever that back-reference and retry
  } else throw e;
}

Prevention

When it happens

Trigger: A payload object assigned to itself (a.self = a), two objects referencing each other (a.b = b; b.a = a), or a tree node whose parent pointer re-enters the graph.

Common situations: Reusing a memoized request object that was mutated to point back at a parent; passing a DOM-like or AST node tree with parent links into the agent payload; building a graph cache and accidentally embedding it.

Related errors


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