danny-avila/LibreChat · error · AgentRunEnvelopeError
${path} contains non-index array properties
Error message
${path} contains non-index array properties What it means
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.
Source
Thrown at packages/api/src/agents/envelope.ts:148
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)) {
if (key === 'length') {
continue;
}
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';View on GitHub (pinned to 5ff282f900)
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.
Example fix
// before
const items = getItems();
items.total = items.length;
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { items } });
// after
const items = getItems();
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { items: [...items], total: items.length } }); Defensive patterns
Strategy: validation
Validate before calling
function arrayHasOnlyIndexKeys(arr: unknown[]): boolean {
for (const key of Object.getOwnPropertyNames(arr)) {
if (key === 'length') continue;
const i = Number(key);
if (!Number.isSafeInteger(i) || i < 0 || i >= arr.length || String(i) !== key) return false;
}
return true;
}
if (Array.isArray(payload.items) && !arrayHasOnlyIndexKeys(payload.items)) {
payload.items = [...payload.items]; // spread drops non-index own props
} Type guard
function isDenseIndexArray(arr: unknown[]): boolean {
const names = Object.getOwnPropertyNames(arr).filter((k) => k !== 'length');
return names.every((k) => {
const i = Number(k);
return Number.isSafeInteger(i) && i >= 0 && i < arr.length && String(i) === k;
});
} Try / catch
try {
const env = createAgentRunEnvelope(input);
} catch (e) {
if (e instanceof AgentRunEnvelopeError && /non-index array properties/.test(e.message)) {
// reconstruct arrays via [...arr] which keeps only indexed elements
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ${path} contains a non-JSON ${typeof value} value
- ${path} contains a circular reference
- ${path} contains symbol keys
- ${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/dc4c502ca36c0d9b.
Report an issue: GitHub.