{"record":{"id":"c4e104af0ced3200","repo":"langchain-ai/langchain","slug":"expected-2-tuple-of-role-template-got-message","errorCode":null,"errorMessage":"Expected 2-tuple of (role, template), got {message}","messagePattern":"Expected 2-tuple of \\(role, template\\), got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/prompts/chat.py","lineNumber":1466,"sourceCode":"        message_ = message\n    elif isinstance(message, str):\n        message_ = _create_template_from_message_type(\n            \"human\", message, template_format=template_format\n        )\n    elif isinstance(message, (tuple, dict)):\n        if isinstance(message, dict):\n            if set(message.keys()) != {\"content\", \"role\"}:\n                msg = (\n                    \"Expected dict to have exact keys 'role' and 'content'.\"\n                    f\" Got: {message}\"\n                )\n                raise ValueError(msg)\n            message_type_str = message[\"role\"]\n            template = message[\"content\"]\n        else:\n            if len(message) != 2:  # noqa: PLR2004\n                msg = f\"Expected 2-tuple of (role, template), got {message}\"  # type: ignore[unreachable]\n                raise ValueError(msg)\n            message_type_str, template = message\n\n        if isinstance(message_type_str, str):\n            message_ = _create_template_from_message_type(\n                message_type_str, template, template_format=template_format\n            )\n        elif (\n            hasattr(message_type_str, \"model_fields\")\n            and \"type\" in message_type_str.model_fields\n        ):\n            message_type = message_type_str.model_fields[\"type\"].default\n            message_ = _create_template_from_message_type(\n                message_type, template, template_format=template_format\n            )\n        else:\n            message_ = message_type_str(\n                prompt=PromptTemplate.from_template(\n                    cast(\"str\", template), template_format=template_format","sourceCodeStart":1448,"sourceCodeEnd":1484,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/prompts/chat.py#L1448-L1484","documentation":"Raised in _convert_to_message_template when a tuple message does not have exactly 2 elements (role, template). Under static typing this branch is marked unreachable (TypedDict/protocol tuples are length-2), but at runtime a longer or shorter tuple reaches it.","triggerScenarios":"`from_messages([(\"user\", \"hi\", \"extra\")])` (3-tuple) or `[\"user\"]` mis-typed as a tuple of one; also `(role, template)` built by unpacking a variable-length list.","commonSituations":"Appending optional third elements (like a name) to message tuples; zipping config arrays of unequal length producing short tuples.","solutions":["Ensure each tuple message is exactly (role, template).","If you have extra data, put it in the template construction afterwards or use a typed message object.","Validate tuple lengths when messages are assembled dynamically."],"exampleFix":"# before\nChatPromptTemplate.from_messages([(\"user\", \"hi\", \"en\")])\n\n# after\nChatPromptTemplate.from_messages([(\"user\", \"hi\")])","handlingStrategy":"validation","validationCode":"def valid_message_tuple(m):\n    return isinstance(m, tuple) and len(m) == 2","typeGuard":"def is_role_template_pair(m) -> bool:\n    return isinstance(m, (tuple, list)) and len(m) == 2 and isinstance(m[0], str)","tryCatchPattern":null,"preventionTips":["Assert length 2 when assembling tuples dynamically.","Don't append optional third elements to message tuples; carry extras in typed message objects."],"tags":["prompts","from-messages","tuple-messages"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}