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

  1. Construct messages with the Langchain constructors (new HumanMessage/AIMessage/SystemMessage) from the SAME @langchain/core the converter uses.
  2. Deduplicate @langchain/core in node_modules (pnpm why / npm ls) so isInstance matches across packages.
  3. 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

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


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/0a3e17bbbb843735. Report an issue: GitHub.