n8n-io/n8n · warning · Error
Reflector output must be a JSON object
Error message
Reflector output must be a JSON object
What it means
Warning thrown by the tool-node validator when a tool node has no parameters set. Most tool nodes need at least one parameter (often a $fromAI description) to be useful to an agent. A small allowlist of tools (calculator, vector stores, MCP client tool, Wikipedia, SerpApi) is exempt.
Source
Thrown at packages/@n8n/agents/src/runtime/memory/observation-log-reflector.ts:71
export type RunObservationLogReflectorResult =
| { status: 'skipped'; reason: 'below-threshold'; tokenCount: number }
| {
status: 'ran';
tokenCount: number;
remainingTokenCount: number;
overBudgetAfterReflection: boolean;
reflection: ObservationLogReflection;
result: ObservationLogReflectionResult;
};
export function parseObservationLogReflectionJson(output: string): ObservationLogReflection {
let parsed: unknown;
try {
parsed = JSON.parse(extractJsonObject(output));
} catch {
throw new Error('Reflector output must be valid JSON');
}
if (!isRecord(parsed)) throw new Error('Reflector output must be a JSON object');
return {
drop: readStringArray(parsed.drop ?? [], 'drop'),
merge: readMergeArray(parsed.merge ?? []),
};
}
export function renderObservationLogForReflection(entries: ObservationLogEntry[]): string {
const activeEntries = entries.filter((entry) => entry.status === 'active').sort(compareEntries);
const activeIds = new Set(activeEntries.map((entry) => entry.id));
const childrenByParent = new Map<string, ObservationLogEntry[]>();
const roots: ObservationLogEntry[] = [];
for (const entry of activeEntries) {
if (entry.parentId && activeIds.has(entry.parentId)) {
const children = childrenByParent.get(entry.parentId) ?? [];
children.push(entry);
childrenByParent.set(entry.parentId, children);View on GitHub (pinned to 5ac6606e81)
Solutions
- Add the parameters the tool needs (e.g. a $fromAI description for each agent-provided argument).
- If the tool genuinely takes no parameters, register it in the node type with an empty properties array so the provider path skips validation.
- Confirm node.type is correct — a misnamed type that happens to contain 'tool' will trigger this check.
Example fix
// before
const t = toolHttp({ name: 'Fetcher' });
// after — add a parameter the agent can supply
toolHttp({
name: 'Fetcher',
parameters: { url: expr('={{ $fromAI.url }}') },
}); Defensive patterns
Strategy: validation
Validate before calling
const TOOLS_WITHOUT_PARAMETERS = new Set([
'@n8n/n8n-nodes-langchain.toolCalculator',
'@n8n/n8n-nodes-langchain.toolVectorStore',
'@n8n/n8n-nodes-langchain.vectorStoreInMemory',
'@n8n/n8n-nodes-langchain.mcpClientTool',
'@n8n/n8n-nodes-langchain.toolWikipedia',
'@n8n/n8n-nodes-langchain.toolSerpApi',
]);
function needsParameters(type: string, params: unknown, propertiesLength: number | undefined): boolean {
if (!/tool/i.test(type)) return false;
if (TOOLS_WITHOUT_PARAMETERS.has(type)) return false;
if (propertiesLength === 0) return false;
return !params || Object.keys(params as object).length === 0;
} Prevention
- Always add at least one $fromAI-described parameter to custom tool nodes.
- Register genuinely parameterless tools with an empty properties array so the provider path skips validation.
- Confirm node.type spelling — types containing 'tool' opt into this check.
When it happens
Trigger: isToolNode(node.type) is true (type contains 'tool'/'Tool'), the node is not in TOOLS_WITHOUT_PARAMETERS, the nodeTypesProvider (if present) does not report an empty properties array, and node.config.parameters is missing or has zero own keys.
Common situations: Adding a custom HTTP/tool node and forgetting its description parameters; an AI builder emits a tool shell without $fromAI fields; the provider info was unavailable so the static allowlist did not cover a parameterless custom tool.
Related errors
- Run ${this.runId} is not suspended. Cannot resume.
- Reflector output must be valid JSON
- Agent run was aborted
- ${turn.errorReason.message}
- Tool name "${RECALL_MEMORY_TOOL_NAME}" is reserved while epi
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/3d8ce2ab0864163a.
Report an issue: GitHub.