{"record":{"id":"a4b5d87d371d9f96","repo":"langchain-ai/langchain","slug":"invalid-placeholder-template-template-expected","errorCode":null,"errorMessage":"Invalid placeholder template: {template}. Expected a variable name surrounded by curly braces.","messagePattern":"Invalid placeholder template: (.+?)\\. Expected a variable name surrounded by curly braces\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/prompts/chat.py","lineNumber":1378,"sourceCode":"        message: BaseMessagePromptTemplate = HumanMessagePromptTemplate.from_template(\n            cast(\"str\", template), template_format=template_format\n        )\n    elif message_type in {\"ai\", \"assistant\"}:\n        message = AIMessagePromptTemplate.from_template(\n            cast(\"str\", template), template_format=template_format\n        )\n    elif message_type == \"system\":\n        message = SystemMessagePromptTemplate.from_template(\n            cast(\"str\", template), template_format=template_format\n        )\n    elif message_type == \"placeholder\":\n        if isinstance(template, str):\n            if template[0] != \"{\" or template[-1] != \"}\":\n                msg = (\n                    f\"Invalid placeholder template: {template}.\"\n                    \" Expected a variable name surrounded by curly braces.\"\n                )\n                raise ValueError(msg)\n            var_name = template[1:-1]\n            message = MessagesPlaceholder(variable_name=var_name, optional=True)\n        else:\n            try:\n                var_name_wrapped, is_optional = template\n            except ValueError as e:\n                msg = (\n                    \"Unexpected arguments for placeholder message type.\"\n                    \" Expected either a single string variable name\"\n                    \" or a list of [variable_name: str, is_optional: bool].\"\n                    f\" Got: {template}\"\n                )\n                raise ValueError(msg) from e\n\n            if not isinstance(is_optional, bool):\n                msg = f\"Expected is_optional to be a boolean. Got: {is_optional}\"\n                raise ValueError(msg)  # noqa: TRY004\n","sourceCodeStart":1360,"sourceCodeEnd":1396,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/prompts/chat.py#L1360-L1396","documentation":"Raised in _create_template_from_message_type when a message tuple declares role \"placeholder\" and the template value is a string that does not start with '{' and end with '}'. A MessagesPlaceholder must reference a variable name surrounded by curly braces, e.g. (\"placeholder\", \"{chat_history}\"), so LangChain can extract the variable name.","triggerScenarios":"Calling `ChatPromptTemplate.from_messages([(\"placeholder\", \"chat_history\")])` — missing braces. Also `(\"placeholder\", \"chat history\")` (spaces instead of braces) or a trailing character like `\"{history} \"`.","commonSituations":"Copy-pasting placeholder syntax from older docs or examples that show the bare variable name; refactoring from MessagesPlaceholder(variable_name=\"history\") to tuple form and forgetting to wrap the name in braces.","solutions":["Wrap the variable name in curly braces: change (\"placeholder\", \"history\") to (\"placeholder\", \"{history}\").","Alternatively pass the structured form (\"placeholder\", [\"{history}\", True]) to also mark it optional.","Or construct MessagesPlaceholder(variable_name=\"history\") directly instead of the tuple shorthand."],"exampleFix":"# before\nChatPromptTemplate.from_messages([(\"placeholder\", \"chat_history\")])\n\n# after\nChatPromptTemplate.from_messages([(\"placeholder\", \"{chat_history}\")])","handlingStrategy":"validation","validationCode":"import re\n\ndef valid_placeholder_string(t):\n    return isinstance(t, str) and re.fullmatch(r\"\\{[a-zA-Z_][a-zA-Z0-9_]*\\}\", t) is not None","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on the {var_name} brace convention for placeholders in code review checklists.","Prefer MessagesPlaceholder(variable_name=...) when the name comes from a variable.","Unit-test prompt construction paths that build placeholder tuples dynamically."],"tags":["prompts","messages-placeholder","from-messages"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}