n8n-io/n8n · error · Error
Reflector field "merge" must be an array
Error message
Reflector field "merge" must be an array
What it means
The reflector JSON contract requires a top-level `merge` field that is an array of merge-instructions. `readMergeArray` throws this when `parsed.merge` is present but not an array (e.g. an object or a string). Note that `parseObservationLogReflectionJson` defaults `merge` to `[]` when absent, so this only fires when the field exists but has the wrong type.
Source
Thrown at packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts:300
throw new Error('Reflector output did not contain a JSON object');
}
return output.slice(start, end + 1);
}
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 }),
};View on GitHub (pinned to 5ac6606e81)
Solutions
- Log the raw reflector output to confirm `merge` is a non-array type.
- Update the reflector system prompt to show `merge` as an array with at least one example element, emphasizing the brackets.
- If the model consistently returns a single object, add a pre-parse normalization step that wraps a lone object into `[object]` before validation.
- Switch to a model or mode that supports structured/JSON-schema-constrained output.
Example fix
// before: { "drop": [], "merge": { "supersedes": ["obs-1"], "marker": "INFO", "text": "..." } }
// after: { "drop": [], "merge": [ { "supersedes": ["obs-1"], "marker": "INFO", "text": "..." } ] } Defensive patterns
Strategy: validation
Validate before calling
const raw = JSON.parse(extractJsonObject(output));
if (raw.merge !== undefined && !Array.isArray(raw.merge)) {
// Normalize: wrap single object in array
if (typeof raw.merge === 'object' && raw.merge !== null) {
raw.merge = [raw.merge];
} else {
raw.merge = [];
}
} Type guard
function isMergeArray(value: unknown): value is unknown[] {
return Array.isArray(value);
} Try / catch
try {
const reflection = parseObservationLogReflectionJson(output);
} catch (e) {
logger.warn('Reflector merge field not an array', { output });
} Prevention
- Show the reflector prompt `merge` as `[...]` with explicit brackets in every example.
- Pre-normalize the parsed JSON: if `merge` is a single object, wrap it in an array.
- Enable structured-output mode to enforce `merge: array` at the API level.
When it happens
Trigger: The reflector LLM returns `{ "merge": { "supersedes": [], "marker": "INFO", "text": "..." } }` (a single object instead of an array) or `{ "merge": "" }`.
Common situations: The model emitted a single merge object rather than wrapping it in an array. The prompt example showed merge as an object, causing the model to mirror that shape. A model with poor array-handling collapsed the array.
Related errors
- Reflector field "${fieldName}" must be an array
- Reflector field "${fieldName}" must contain only strings
- Reflector merge[${index}] must be an object
- Reflector merge[${index}].text must be a string
- Reflector merge[${index}].marker must be a known observation
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/88b1367adbee3325.
Report an issue: GitHub.