{"record":{"id":"dc4c502ca36c0d9b","repo":"danny-avila/LibreChat","slug":"path-contains-non-index-array-properties","errorCode":null,"errorMessage":"${path} contains non-index array properties","messagePattern":"(.+?) contains non-index array properties","errorType":"validation","errorClass":"AgentRunEnvelopeError","httpStatus":null,"severity":"error","filePath":"packages/api/src/agents/envelope.ts","lineNumber":148,"sourceCode":"    if (symbolKeys.length > 0) {\n      throw new AgentRunEnvelopeError(`${path} contains symbol keys`);\n    }\n\n    if (Array.isArray(value)) {\n      const cloned: unknown[] = new Array(value.length);\n      let clonedItemCount = 0;\n      for (const key of Object.getOwnPropertyNames(value)) {\n        if (key === 'length') {\n          continue;\n        }\n        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';","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/agents/envelope.ts#L130-L166","documentation":"Thrown by cloneJsonValue for an Array payload value that has own properties whose keys are not valid array indices: the key must parse to a safe integer >= 0, < array.length, and String(index) must equal the key (so '01', '1.0', '-1', 'foo' all fail). JSON arrays only support integer-indexed elements; extra named props would be silently lost, so the clone surfaces them as an error.","triggerScenarios":"Attaching a named property to an array (arr.count = 5, arr['meta'] = {...}), a negative or fractional key, or a string key like '01' that round-trips to a different index. Also arr.foo after Object.defineProperty.","commonSituations":"Using an array as a carrier for both a list and metadata (arr.total = n); libraries that annotate arrays with named fields; copying an array-like collection (arguments, NodeList) that gained extra props.","solutions":["Move any named properties off the array into a sibling object ({ items: [...], meta: {...} }).","If the named prop is stray metadata, delete it before building the envelope (delete arr.foo).","Reconstruct the array via Array.from or spread ([...arr]) which drops non-index own properties."],"exampleFix":"// before\nconst items = getItems();\nitems.total = items.length;\ncreateAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { items } });\n\n// after\nconst items = getItems();\ncreateAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { items: [...items], total: items.length } });","handlingStrategy":"validation","validationCode":"function arrayHasOnlyIndexKeys(arr: unknown[]): boolean {\n  for (const key of Object.getOwnPropertyNames(arr)) {\n    if (key === 'length') continue;\n    const i = Number(key);\n    if (!Number.isSafeInteger(i) || i < 0 || i >= arr.length || String(i) !== key) return false;\n  }\n  return true;\n}\nif (Array.isArray(payload.items) && !arrayHasOnlyIndexKeys(payload.items)) {\n  payload.items = [...payload.items]; // spread drops non-index own props\n}","typeGuard":"function isDenseIndexArray(arr: unknown[]): boolean {\n  const names = Object.getOwnPropertyNames(arr).filter((k) => k !== 'length');\n  return names.every((k) => {\n    const i = Number(k);\n    return Number.isSafeInteger(i) && i >= 0 && i < arr.length && String(i) === k;\n  });\n}","tryCatchPattern":"try {\n  const env = createAgentRunEnvelope(input);\n} catch (e) {\n  if (e instanceof AgentRunEnvelopeError && /non-index array properties/.test(e.message)) {\n    // reconstruct arrays via [...arr] which keeps only indexed elements\n  } else throw e;\n}","preventionTips":["Never attach named metadata to an array; wrap as { items: [...], meta: {...} }.","Use [...arr] or Array.from(arr) when copying arrays that may carry stray props.","Lint for arr.<name> = assignments in code that feeds the envelope payload."],"tags":["serialization","json","array","agent-envelope","payload-validation"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}