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

  1. Replace new Array(n) with Array.from({ length: n }, () => null) so every slot has a value.
  2. Use splice(i, 1) instead of delete arr[i] to keep the array dense.
  3. 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

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


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