n8n-io/n8n · error · Error
Reflector merge[${index}] must be an object
Error message
Reflector merge[${index}] must be an object What it means
Each element of the `merge` array must be a JSON object (record) with `supersedes`, `marker`, `text`, and optional `parentId` fields. `readMerge` calls `isRecord(value)` and throws if the element is not a plain object — for example a bare string, number, or null. The `index` in the message tells you which array position is malformed.
Source
Thrown at packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts:305
function readStringArray(value: unknown, fieldName: string): string[] {
if (!Array.isArray(value)) throw new Error(`Reflector field "${fieldName}" must be an array`);
const strings: string[] = [];
for (const item of value) {
if (typeof item !== 'string') {
throw new Error(`Reflector field "${fieldName}" must contain only strings`);
}
strings.push(item);
}
return strings;
}
function readMergeArray(value: unknown): ObservationLogMerge[] {
if (!Array.isArray(value)) throw new Error('Reflector field "merge" must be an array');
return value.map(readMerge);
}
function readMerge(value: unknown, index: number): ObservationLogMerge {
if (!isRecord(value)) throw new Error(`Reflector merge[${index}] must be an object`);
const supersedes = readStringArray(value.supersedes, `merge[${index}].supersedes`);
const marker = readMarker(value.marker, index);
if (typeof value.text !== 'string') {
throw new Error(`Reflector merge[${index}].text must be a string`);
}
const parentId = readOptionalParentId(value.parentId, index);
return {
supersedes,
marker,
text: value.text,
...(parentId !== undefined && { parentId }),
};
}
function readMarker(value: unknown, index: number): ObservationLogMarker {
if (typeof value !== 'string') {
throw new Error(`Reflector merge[${index}].marker must be a known observation marker`);View on GitHub (pinned to 5ac6606e81)
Solutions
- Use the `index` from the error message to locate the offending element in the raw LLM output.
- Update the reflector prompt: each `merge` element must be a complete object with `supersedes`, `marker`, and `text`; never emit bare text or null.
- If truncation is the cause, increase the model's `maxOutputTokens` or reduce the observation-log input size so the reflector has budget to finish.
- Enable structured-output / JSON mode on the provider to enforce the object shape at the API level.
Example fix
// before: { "merge": [ "replace obs-1", { "supersedes": [...], ... } ] }
// after: { "merge": [ { "supersedes": ["obs-1"], "marker": "INFO", "text": "replace obs-1" } ] } Defensive patterns
Strategy: type-guard
Validate before calling
import { isRecord } from '@n8n/utils/is-record';
const raw = JSON.parse(extractJsonObject(output));
if (Array.isArray(raw.merge)) {
raw.merge = raw.merge.filter(isRecord); // drop non-object elements
} Type guard
import { isRecord } from '@n8n/utils/is-record';
function isMergeObject(value: unknown): value is Record<string, unknown> {
return isRecord(value);
} Try / catch
try {
const reflection = parseObservationLogReflectionJson(output);
} catch (e) {
logger.warn('Reflector merge element not an object', { index: 'see message', output });
} Prevention
- Filter non-object elements from the merge array before parsing.
- Use structured-output / JSON-schema mode with `merge: array<object>`.
- Ensure the reflector prompt shows complete merge objects in examples.
When it happens
Trigger: The reflector LLM returns `{ "merge": ["just text", { ... }] }` where `merge[0]` is a string instead of an object, or `{ "merge": [null] }`.
Common situations: The model produced a mixed array of strings and objects. The model used `null` as a placeholder for a merge it could not produce. A truncated response cut off mid-object, leaving a bare value.
Related errors
- Reflector field "${fieldName}" must contain only strings
- Reflector merge[${index}].marker must be a known observation
- Reflector merge[${index}].parentId must be a string or null
- Reflector field "${fieldName}" must be an array
- Reflector field "merge" must be an array
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/2a85ec3539976836.
Report an issue: GitHub.