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
- Inspect the path in the message (e.g. 'payload.messages[2].content') to locate the offending field.
- Replace undefined fields with null, strip function references, and convert BigInt to string/number before building the envelope.
- 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
- Never spread untyped/SDK objects into the payload; pick fields explicitly.
- Default optional fields to null rather than leaving them undefined.
- Run JSON.parse(JSON.stringify(payload)) in dev/test before calling createAgentRunEnvelope to catch non-JSON values early.
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
- ${path} contains a circular reference
- ${path} contains symbol keys
- ${path} contains non-index array properties
- ${path}[${index}] must not be an accessor property
- ${path} contains sparse array entries
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/c800d199c4266df6.
Report an issue: GitHub.