{"record":{"id":"abb106157344a317","repo":"danny-avila/LibreChat","slug":"path-contains-sparse-array-entries","errorCode":null,"errorMessage":"${path} contains sparse array entries","messagePattern":"(.+?) contains sparse array entries","errorType":"validation","errorClass":"AgentRunEnvelopeError","httpStatus":null,"severity":"error","filePath":"packages/api/src/agents/envelope.ts","lineNumber":159,"sourceCode":"        const index = Number(key);\n        if (\n          !Number.isSafeInteger(index) ||\n          index < 0 ||\n          index >= value.length ||\n          String(index) !== key\n        ) {\n          throw new AgentRunEnvelopeError(`${path} contains non-index array properties`);\n        }\n        const descriptor = Object.getOwnPropertyDescriptor(value, key);\n        if (!descriptor || !Object.prototype.hasOwnProperty.call(descriptor, 'value')) {\n          throw new AgentRunEnvelopeError(`${path}[${index}] must not be an accessor property`);\n        }\n        const itemValue: unknown = descriptor.value;\n        cloned[index] = cloneJsonValue(itemValue, `${path}[${index}]`, ancestors, depth + 1);\n        clonedItemCount++;\n      }\n      if (clonedItemCount !== value.length) {\n        throw new AgentRunEnvelopeError(`${path} contains sparse array entries`);\n      }\n      return cloned;\n    }\n\n    const prototype = Object.getPrototypeOf(value);\n    if (prototype !== Object.prototype && prototype !== null) {\n      const typeName = value.constructor?.name ?? 'object';\n      throw new AgentRunEnvelopeError(`${path} contains a non-plain ${typeName} value`);\n    }\n\n    const cloned: { [key: string]: unknown } = {};\n    for (const key of Object.getOwnPropertyNames(value)) {\n      const descriptor = Object.getOwnPropertyDescriptor(value, key);\n      if (descriptor?.enumerable !== true) {\n        throw new AgentRunEnvelopeError(`${path}.${key} must be an enumerable property`);\n      }\n      if (!Object.prototype.hasOwnProperty.call(descriptor, 'value')) {\n        throw new AgentRunEnvelopeError(`${path}.${key} must not be an accessor property`);","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/agents/envelope.ts#L141-L177","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst slots = new Array(5);\nslots[0] = 'a';\ncreateAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { slots } });\n\n// after\nconst slots = Array.from({ length: 5 }, () => null);\nslots[0] = 'a';\ncreateAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { slots } });","handlingStrategy":"validation","validationCode":"function isDenseArray(arr: unknown[]): boolean {\n  for (let i = 0; i < arr.length; i++) {\n    if (!(i in arr)) return false; // hole present\n  }\n  return true;\n}\nif (Array.isArray(payload.slots) && !isDenseArray(payload.slots)) {\n  payload.slots = payload.slots.map((v) => (v === undefined ? null : v));\n}","typeGuard":"function isDenseArray(arr: unknown[]): boolean {\n  return arr.every((_, i) => i in arr);\n}","tryCatchPattern":"try {\n  const env = createAgentRunEnvelope(input);\n} catch (e) {\n  if (e instanceof AgentRunEnvelopeError && /sparse array/.test(e.message)) {\n    // fill holes with null: payload.slots = payload.slots.map(v => v === undefined ? null : v);\n  } else throw e;\n}","preventionTips":["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."],"tags":["serialization","json","array","sparse-array","agent-envelope"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}