danny-avila/LibreChat · error · AgentRunEnvelopeError
${path} contains sparse array entries
Error message
${path} contains sparse array entries What it means
Thrown by cloneJsonValue when an Array's own enumerable index-property count does not equal its .length, i.e. the array has holes (sparse arrays). Examples: new Array(5), [1, , 3], or deleting an element with the delete operator. JSON.stringify turns holes into null, which would silently corrupt data; the clone makes the discrepancy explicit.
Source
Thrown at packages/api/src/agents/envelope.ts:159
const index = Number(key);
if (
!Number.isSafeInteger(index) ||
index < 0 ||
index >= value.length ||
String(index) !== key
) {
throw new AgentRunEnvelopeError(`${path} contains non-index array properties`);
}
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (!descriptor || !Object.prototype.hasOwnProperty.call(descriptor, 'value')) {
throw new AgentRunEnvelopeError(`${path}[${index}] must not be an accessor property`);
}
const itemValue: unknown = descriptor.value;
cloned[index] = cloneJsonValue(itemValue, `${path}[${index}]`, ancestors, depth + 1);
clonedItemCount++;
}
if (clonedItemCount !== value.length) {
throw new AgentRunEnvelopeError(`${path} contains sparse array entries`);
}
return cloned;
}
const prototype = Object.getPrototypeOf(value);
if (prototype !== Object.prototype && prototype !== null) {
const typeName = value.constructor?.name ?? 'object';
throw new AgentRunEnvelopeError(`${path} contains a non-plain ${typeName} value`);
}
const cloned: { [key: string]: unknown } = {};
for (const key of Object.getOwnPropertyNames(value)) {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
if (descriptor?.enumerable !== true) {
throw new AgentRunEnvelopeError(`${path}.${key} must be an enumerable property`);
}
if (!Object.prototype.hasOwnProperty.call(descriptor, 'value')) {
throw new AgentRunEnvelopeError(`${path}.${key} must not be an accessor property`);View on GitHub (pinned to 5ff282f900)
Solutions
- Replace new Array(n) with Array.from({ length: n }, () => null) so every slot has a value.
- Use splice(i, 1) instead of delete arr[i] to keep the array dense.
- Run arr.every((_, i) => i in arr) before building the envelope; fill holes with null if appropriate.
Example fix
// before
const slots = new Array(5);
slots[0] = 'a';
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { slots } });
// after
const slots = Array.from({ length: 5 }, () => null);
slots[0] = 'a';
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { slots } }); Defensive patterns
Strategy: validation
Validate before calling
function isDenseArray(arr: unknown[]): boolean {
for (let i = 0; i < arr.length; i++) {
if (!(i in arr)) return false; // hole present
}
return true;
}
if (Array.isArray(payload.slots) && !isDenseArray(payload.slots)) {
payload.slots = payload.slots.map((v) => (v === undefined ? null : v));
} Type guard
function isDenseArray(arr: unknown[]): boolean {
return arr.every((_, i) => i in arr);
} Try / catch
try {
const env = createAgentRunEnvelope(input);
} catch (e) {
if (e instanceof AgentRunEnvelopeError && /sparse array/.test(e.message)) {
// fill holes with null: payload.slots = payload.slots.map(v => v === undefined ? null : v);
} else throw e;
} Prevention
- Use Array.from({ length: n }, () => null) instead of new Array(n).
- Prefer splice(i, 1) over delete arr[i] to keep arrays dense.
- Add a test asserting arrays in the payload have no holes.
When it happens
Trigger: Creating new Array(n) and filling only some slots; producing an array with trailing/intermediate holes via delete arr[i]; an array built by assigning to non-contiguous indices.
Common situations: Preallocating an array of a fixed size but not filling every index; deleting elements from the middle of an array instead of splicing; deserializing sparse data structures.
Related errors
- ${path} contains non-index array properties
- ${path}[${index}] must not be an accessor property
- ${path} contains a non-JSON ${typeof value} value
- ${path} contains a circular reference
- ${path} contains symbol keys
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/abb106157344a317.
Report an issue: GitHub.