danny-avila/LibreChat · error · AgentRunEnvelopeError

${path} contains a non-JSON ${typeof value} value

Error message

${path} contains a non-JSON ${typeof value} value

What it means

Thrown by cloneJsonValue inside createAgentRunEnvelope when a value anywhere in the agent-run payload has a non-JSON typeof ('undefined', 'function', 'bigint', or 'symbol'). The envelope must cross the execution seam as pure JSON, so any value JSON.stringify would drop or reject is refused here. This guard exists because a leaked function/closure can pull runtime state (DB clients, credentials, Express req) into the sandbox payload.

Source

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

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

  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)) {

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Inspect the path in the message (e.g. 'payload.messages[2].content') to locate the offending field.
  2. Replace undefined fields with null, strip function references, and convert BigInt to string/number before building the envelope.
  3. Add a pre-flight isPlainJsonValue check (see defense) over the payload before calling createAgentRunEnvelope.

Example fix

// before
const payload = { ...req, onCancel: () => abortController.abort() };
const env = createAgentRunEnvelope({ protocol: 'chat.completions', requestId, receivedAt, principal, payload });

// after
const { onCancel, ...serializable } = req;
const payload = { ...serializable, onCancel: null };
const env = createAgentRunEnvelope({ protocol: 'chat.completions', requestId, receivedAt, principal, payload });
Defensive patterns

Strategy: type-guard

Validate before calling

const NON_JSON_TYPES = new Set(['undefined', 'function', 'bigint', 'symbol']);
function hasNonJsonValue(value: unknown, path = 'payload'): string | null {
  const t = typeof value;
  if (value === null || t === 'string' || t === 'boolean') return null;
  if (t === 'number') return Number.isFinite(value) ? null : `${path} must contain only finite numbers`;
  if (NON_JSON_TYPES.has(t)) return `${path} contains a non-JSON ${t} value`;
  return null;
}
// before building the envelope:
for (const [k, v] of Object.entries(payload)) {
  const err = hasNonJsonValue(v, `payload.${k}`);
  if (err) throw new Error(err);
}

Type guard

function isJsonScalar(value: unknown): value is string | number | boolean | null {
  if (value === null || typeof value === 'string' || typeof value === 'boolean') return true;
  if (typeof value === 'number') return Number.isFinite(value);
  return false; // undefined, function, bigint, symbol
}

Try / catch

try {
  const env = createAgentRunEnvelope(input);
} catch (e) {
  if (e instanceof AgentRunEnvelopeError && /non-JSON/.test(e.message)) {
    // sanitize payload: drop undefined fields, convert BigInt to String
  } else throw e;
}

Prevention

When it happens

Trigger: A payload field set to undefined, a function reference, a BigInt (e.g. 123n), or a Symbol value. Common: an extension field left undefined; a callback accidentally attached to the request object; a numeric ID parsed as BigInt before being placed in the payload.

Common situations: Adding a new AgentRunPayloadExtensions field and forgetting to default it; converting numeric IDs to BigInt for precision and passing them through; copying a provider SDK request object whose prototype carries function-valued options.

Related errors


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