danny-avila/LibreChat · error · AgentRunEnvelopeError
${path}.${key} must not be an accessor property
Error message
${path}.${key} must not be an accessor property What it means
Thrown by cloneJsonValue when a plain object's own enumerable property is an accessor (defined with get/set) rather than a data value. The descriptor lacks an own 'value' key. Getters can throw or have side effects, so the clone refuses to invoke them and demands a concrete value.
Source
Thrown at packages/api/src/agents/envelope.ts:177
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`);
}
const propertyValue: unknown = descriptor.value;
Object.defineProperty(cloned, key, {
configurable: true,
enumerable: true,
writable: true,
value: cloneJsonValue(propertyValue, `${path}.${key}`, ancestors, depth + 1),
});
}
return cloned;
} finally {
ancestors.delete(value);
}
}
function createPrincipal(input: AgentRunPrincipalInput | null | undefined): AgentRunPrincipal {
const userId = assertNonEmptyString(input?.id, 'principal.id');
const principal: AgentRunPrincipal = { userId };View on GitHub (pinned to 5ff282f900)
Solutions
- Evaluate getters into plain values: build { k: obj.k } by reading each field explicitly.
- Replace accessor descriptors with data descriptors (defineProperty with value).
- Use Object.entries(obj) to harvest concrete values into a fresh literal.
Example fix
// before
Object.defineProperty(meta, 'summary', { get() { return title + ' - ' + body; }, enumerable: true });
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { meta } });
// after
const meta = { summary: title + ' - ' + body };
createAgentRunEnvelope({ protocol, requestId, receivedAt, principal, payload: { meta } }); Defensive patterns
Strategy: validation
Validate before calling
function objectHasOnlyDataValues(obj: Record<string, unknown>): boolean {
return Object.getOwnPropertyNames(obj).every((k) => {
const d = Object.getOwnPropertyDescriptor(obj, k);
return !!d && Object.prototype.hasOwnProperty.call(d, 'value');
});
}
function materializeGetters<T extends Record<string, unknown>>(obj: T): Record<string, unknown> {
const out: Record<string, unknown> = {};
for (const k of Object.keys(obj)) out[k] = obj[k]; // invoke getter, store value
return out;
} Type guard
function isDataPropsOnly(obj: Record<PropertyKey, unknown>): boolean {
return Object.getOwnPropertyNames(obj).every((k) => {
const d = Object.getOwnPropertyDescriptor(obj, k);
return !!d && Object.prototype.hasOwnProperty.call(d, 'value');
});
} Try / catch
try {
const env = createAgentRunEnvelope(input);
} catch (e) {
if (e instanceof AgentRunEnvelopeError && /accessor property/.test(e.message)) {
input.payload = JSON.parse(JSON.stringify(input.payload)) as typeof input.payload;
// getters are invoked and results stored as plain values
} else throw e;
} Prevention
- Do not define getters on payload objects; compute values up front into plain fields.
- Run a JSON round-trip in tests to confirm no accessors survive into the envelope.
- Build payloads from explicit field assignment rather than class instances with getters.
When it happens
Trigger: Object.defineProperty(obj, 'k', { get() {...}, enumerable: true }), a class instance turned plain-ish via assignment but still carrying getters, or a Proxy whose trap surfaces as an accessor descriptor.
Common situations: Computed/derived fields exposed as getters on a config object; interop with libraries that expose lazy properties; spreading a class instance into a plain object while getters survive.
Related errors
- ${path}[${index}] must not be an accessor property
- ${path}.${key} must be an enumerable 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/1a60a5d037684188.
Report an issue: GitHub.