langchain-ai/langchain · error · ValueError
Expected is_optional to be a boolean. Got: {is_optional}
Error message
Expected is_optional to be a boolean. Got: {is_optional} What it means
Raised in _create_template_from_message_type when a structured placeholder spec ["{name}", is_optional] is given but the second element is not a bool. LangChain explicitly type-checks the optional flag because truthy values like 1 or "yes" would silently behave as positional/keyword confusion later.
Source
Thrown at libs/core/langchain_core/prompts/chat.py:1395
)
raise ValueError(msg)
var_name = template[1:-1]
message = MessagesPlaceholder(variable_name=var_name, optional=True)
else:
try:
var_name_wrapped, is_optional = template
except ValueError as e:
msg = (
"Unexpected arguments for placeholder message type."
" Expected either a single string variable name"
" or a list of [variable_name: str, is_optional: bool]."
f" Got: {template}"
)
raise ValueError(msg) from e
if not isinstance(is_optional, bool):
msg = f"Expected is_optional to be a boolean. Got: {is_optional}"
raise ValueError(msg) # noqa: TRY004
if not isinstance(var_name_wrapped, str):
msg = f"Expected variable name to be a string. Got: {var_name_wrapped}"
raise ValueError(msg) # noqa: TRY004
if var_name_wrapped[0] != "{" or var_name_wrapped[-1] != "}":
msg = (
f"Invalid placeholder template: {var_name_wrapped}."
" Expected a variable name surrounded by curly braces."
)
raise ValueError(msg)
var_name = var_name_wrapped[1:-1]
message = MessagesPlaceholder(variable_name=var_name, optional=is_optional)
else:
msg = (
f"Unexpected message type: {message_type}. Use one of 'human',"
f" 'user', 'ai', 'assistant', or 'system'."
)View on GitHub (pinned to e32fa9a52e)
Solutions
- Coerce the flag to a real Python bool: bool(value) or fix the config to emit true/false.
- When loading prompts from JSON, normalize with `spec[1] = bool(spec[1])` before calling from_messages.
- Prefer the plain string form ("placeholder", "{name}") if you don't need to control optionality.
Example fix
# before
ChatPromptTemplate.from_messages([("placeholder", ["{history}", "true"])])
# after
ChatPromptTemplate.from_messages([("placeholder", ["{history}", True])]) Defensive patterns
Strategy: validation
Validate before calling
def normalize_placeholder_spec(spec):
name, optional = spec
if not isinstance(optional, bool):
spec[1] = bool(optional)
return spec Type guard
def is_bool_optional(spec) -> bool:
return len(spec) == 2 and isinstance(spec[1], bool) Prevention
- Normalize booleans after loading prompts from JSON/YAML ("true"/1 are not bool).
- Use JSON schema validation with type: boolean for config-driven prompts.
When it happens
Trigger: `("placeholder", ["{history}", 1])`, `("placeholder", ["{history}", "true"])`, or `("placeholder", ["{history}", None])` inside from_messages.
Common situations: JSON/YAML-config-driven prompt definitions where booleans arrive as strings or 0/1 integers after deserialization; passing a numpy bool or an Optional flag from a config schema.
Related errors
- Expected variable name to be a string. Got: {var_name_wrappe
- Invalid placeholder template: {template}. Expected a variabl
- Unexpected arguments for placeholder message type. Expected
- Invalid placeholder template: {var_name_wrapped}. Expected a
- Unsupported message type: {type(message)}
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/f8603ad1cc541d05.
Report an issue: GitHub.