n8n-io/n8n · error · Error
Provided message is not a valid Langchain message: ${JSON.st
Error message
Provided message is not a valid Langchain message: ${JSON.stringify(msg)} What it means
In the message converter, after checking for AIMessage, SystemMessage, HumanMessage, and the base BaseMessage (via LangchainMessages.*.isInstance), any input that is none of these is rejected. The function expects a real Langchain.js message instance; anything else (a plain object, a string, a mistyped message from another Langchain version) cannot be converted to the n8n message shape.
Source
Thrown at packages/@n8n/ai-utilities/src/converters/message.ts:253
};
}
if (LangchainMessages.HumanMessage.isInstance(msg)) {
return {
role: 'user',
content: fromLcContent(msg.content),
id: msg.id,
name: msg.name,
};
}
if (LangchainMessages.BaseMessage.isInstance(msg)) {
return {
role: fromLcRole(msg.type),
content: fromLcContent(msg.content),
id: msg.id,
name: msg.name,
};
}
throw new Error(`Provided message is not a valid Langchain message: ${JSON.stringify(msg)}`);
}
export function toLcContent(block: N8nMessages.MessageContent): LangchainMessages.ContentBlock {
if (isN8nTextBlock(block)) {
return { type: 'text', text: block.text };
}
if (isN8nReasoningBlock(block)) {
return { type: 'reasoning', reasoning: block.text };
}
if (isN8nFileBlock(block)) {
const { url, fileId, ...rest } = block.providerMetadata ?? {};
return {
type: 'file',
mimeType: block.mediaType ?? 'application/octet-stream',
data: block.data,
...(url ? { url } : {}),
...(fileId ? { fileId } : {}),
...(Object.keys(rest).length > 0 ? { metadata: rest } : {}),View on GitHub (pinned to 5ac6606e81)
Solutions
- Construct messages with the Langchain constructors (new HumanMessage/AIMessage/SystemMessage) from the SAME @langchain/core the converter uses.
- Deduplicate @langchain/core in node_modules (pnpm why / npm ls) so isInstance matches across packages.
- If converting from n8n shapes, use toLcMessage rather than passing raw objects to this function.
Example fix
// before
fromLcMessage({ role: 'user', content: 'hi' });
// after
import { HumanMessage } from '@n8n/langchain/messages';
fromLcMessage(new HumanMessage('hi')); Defensive patterns
Strategy: type-guard
Validate before calling
import { BaseMessage } from '@n8n/langchain/messages';
function isLangchainMessage(m: unknown): m is BaseMessage {
return BaseMessage.isInstance(m) || m instanceof BaseMessage;
}
if (!isLangchainMessage(msg)) throw new Error('pass a real Langchain message instance'); Type guard
import { BaseMessage } from '@n8n/langchain/messages';
function isLangchainMessage(m: unknown): m is BaseMessage {
return m instanceof BaseMessage || (typeof BaseMessage.isInstance === 'function' && BaseMessage.isInstance(m));
} Prevention
- Construct messages with the Langchain constructors from the SAME @langchain/core the converter uses.
- Deduplicate @langchain/core (pnpm why @langchain/core) so isInstance works across packages.
- Convert n8n shapes via toLcMessage; don't hand-build Langchain-like objects.
When it happens
Trigger: Passing a plain `{ role, content }` object instead of a Langchain message instance; passing a message constructed by a different/incompatible @langchain/core version (isInstance returns false across versions); passing a string, null, or a ChatPromptValue.
Common situations: Multiple @langchain/core versions in node_modules (nested installs) so `instanceof`/isInstance fails across the boundary; hand-building message-like objects instead of using the Langchain constructors; version drift after an upgrade.
Related errors
- Failed to convert to Langchain content block: ${JSON.stringi
- Tool message is missing a tool-result content block
- Unable to convert tool to N8nTool: ${JSON.stringify(tool)}
- Run ${this.runId} is not suspended. Cannot resume.
- Reflector output must be valid JSON
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/0a3e17bbbb843735.
Report an issue: GitHub.