{"record":{"id":"0df3ff3d35128e4f","repo":"n8n-io/n8n","slug":"no-message-provided","errorCode":null,"errorMessage":"No message provided","messagePattern":"No message provided","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/ai-workflow-builder.ee/evaluations/langsmith/types.ts","lineNumber":59,"sourceCode":"// Helper to format violations for display\nexport function formatViolations(violations: Array<{ type: string; description: string }>): string {\n\tif (violations.length === 0) {\n\t\treturn 'All checks passed';\n\t}\n\treturn `Found ${violations.length} violation(s): ${violations\n\t\t.map((v) => `${v.type} - ${v.description}`)\n\t\t.join('; ')}`;\n}\n\n// Generate a unique run ID\nexport function generateRunId(): string {\n\treturn `eval-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\n// Validate and extract message content\nexport function extractMessageContent(message: BaseMessage | undefined): string {\n\tif (!message) {\n\t\tthrow new Error('No message provided');\n\t}\n\n\t// @ts-expect-error We need to extract content from kwargs as that's how Langsmith messages are structured\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\tconst content = message.content ?? message.kwargs?.content;\n\n\tif (typeof content === 'string') {\n\t\treturn cleanContextTags(content);\n\t}\n\n\tif (Array.isArray(content)) {\n\t\t// Extract text from complex content\n\t\tconst textContent = content\n\t\t\t.filter((item) => item?.type === 'text')\n\t\t\t.map((item) => (item as { text: string }).text)\n\t\t\t.map(cleanContextTags)\n\t\t\t.join('\\n');\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/ai-workflow-builder.ee/evaluations/langsmith/types.ts#L41-L77","documentation":"`extractMessageContent` pulls text out of a LangChain `BaseMessage`; it rejects `undefined` immediately because every downstream operation (`message.content`, `.kwargs.content`) dereferences the message. Throwing early with a precise message avoids an opaque 'cannot read properties of undefined' from the LangSmith message plumbing.","triggerScenarios":"Calling `extractMessageContent(undefined)` directly, or indirectly via `extractPrompt` when `inputs.messages` exists but `messages[0]` is undefined (sparse array), or via history extraction where a turn is missing.","commonSituations":"Dataset example whose `messages` array is `[, something]` (hole), or a code path that calls `extractMessageContent(arr[index])` without bounds-checking; refactor that swapped a single message for an array and forgot the index.","solutions":["Bounds- and presence-check before calling: `if (!messages?.[0]) throw ...; extractMessageContent(messages[0])`.","Filter sparse entries out of the array first: `messages.filter(Boolean)`.","At the dataset source, ensure every example has at least one well-formed message."],"exampleFix":"// before\nconst text = extractMessageContent(inputs.messages[0]); // inputs.messages[0] is undefined\n// after\nconst first = inputs.messages?.find(Boolean);\nif (!first) throw new Error('dataset example has no message');\nconst text = extractMessageContent(first);","handlingStrategy":"type-guard","validationCode":"function firstMessage(messages: unknown[] | undefined): BaseMessage | undefined {\n  if (!Array.isArray(messages) || messages.length === 0) return undefined;\n  return messages.find((m) => m != null) as BaseMessage | undefined;\n}\nconst m = firstMessage(inputs.messages);\nif (!m) throw new Error('dataset example has no message to extract');\nconst text = extractMessageContent(m);","typeGuard":"function isPresentMessage(v: unknown): v is BaseMessage {\n  return v != null && typeof (v as { content?: unknown }).content !== 'undefined';\n}","tryCatchPattern":null,"preventionTips":["Always bounds- and presence-check arrays of messages before indexing.","Filter sparse arrays (`arr.filter(Boolean)`) before picking the first element.","Add a lint rule against bare `arr[0]` dereferences in code paths that feed `extractMessageContent`."],"tags":["langsmith","types","validation","messages"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}