{"record":{"id":"89240d5ca0a4e94c","repo":"langchain-ai/langchain","slug":"message-as-a-sequence-must-be-role-string-templa","errorCode":null,"errorMessage":"Message as a sequence must be (role string, template)","messagePattern":"Message as a sequence must be \\(role string, template\\)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/messages/utils.py","lineNumber":742,"sourceCode":"    Returns:\n        An instance of a message or a message template.\n\n    Raises:\n        NotImplementedError: if the message type is not supported.\n        ValueError: if the message dict does not contain the required keys.\n\n    \"\"\"\n    if isinstance(message, BaseMessage):\n        message_ = message\n    elif isinstance(message, Sequence):\n        if isinstance(message, str):\n            message_ = _create_message_from_message_type(\"human\", message)\n        else:\n            try:\n                message_type_str, template = message\n            except ValueError as e:\n                msg = \"Message as a sequence must be (role string, template)\"\n                raise NotImplementedError(msg) from e\n            message_ = _create_message_from_message_type(message_type_str, template)\n    elif isinstance(message, dict):\n        # `Serializable` constructor-envelope wire shape. Detect structurally, map\n        # the class name to a known message-type string via a hardcoded\n        # allowlist, and recurse with the canonical\n        # `{\"type\": ..., **kwargs}` shape — no `load()`, no dynamic\n        # class instantiation.\n        if (\n            message.get(\"lc\") == 1\n            and message.get(\"type\") == \"constructor\"\n            and isinstance(message.get(\"id\"), list)\n            and message[\"id\"]\n            and isinstance(message.get(\"kwargs\"), dict)\n        ):\n            mapped = _LC_CONSTRUCTOR_NAME_TO_TYPE.get(message[\"id\"][-1])\n            if mapped is not None:\n                return _convert_to_message({\"type\": mapped, **message[\"kwargs\"]})\n","sourceCodeStart":724,"sourceCodeEnd":760,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/messages/utils.py#L724-L760","documentation":"Raised (as `NotImplementedError`) by `convert_to_messages` when a sequence-form message cannot be unpacked into exactly two elements `(role_string, template)`. Sequences are only supported in the strict 2-tuple form; anything else (3-tuple, 1-tuple, or a non-string sequence misused) hits this.","triggerScenarios":"Passing `('human', 'hi', 'extra')`, `('human',)`, or a list whose unpacking raises `ValueError` inside the `message_type_str, template = message` statement.","commonSituations":"Building message tuples programmatically and accidentally appending extra fields; passing a 3-element tuple intended for another API; a list of characters when a string was expected (though bare strings take the human path).","solutions":["Use exactly 2-element tuples: `(role_str, content)`","Validate tuple length before passing: `assert len(t) == 2`","Prefer the dict form `{'type': role, 'content': content}` for anything with extra fields"],"exampleFix":"# before\nconvert_to_messages([('human', 'hi', {'meta': 1})])\n\n# after\nconvert_to_messages([('human', 'hi')])\n# extra data goes in the dict form instead:\n# [{'type': 'human', 'content': 'hi', 'additional_kwargs': {'meta': 1}}]","handlingStrategy":"validation","validationCode":"def is_valid_tuple_message(m) -> bool:\n    return isinstance(m, tuple) and len(m) == 2 and isinstance(m[0], str)","typeGuard":"def is_role_template_pair(m: object) -> bool:\n    return (isinstance(m, (tuple, list)) and len(m) == 2\n            and isinstance(m[0], str) and isinstance(m[1], (str, list)))","tryCatchPattern":"try:\n    msgs = convert_to_messages(raw)\nexcept NotImplementedError as e:\n    if 'sequence must be (role string, template)' in str(e):\n        raw = [(r, c) for r, c, *_ in (m if len(m) > 2 else (*m, None) for m in raw if isinstance(m, (tuple, list)))]\n        msgs = convert_to_messages(raw)\n    else:\n        raise","preventionTips":["Standardize on 2-tuples when building message tuples","Prefer dict form for messages carrying extra fields","Assert tuple shape in tests for message-building helpers"],"tags":["message-coercion","tuples","input-validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}