hiyouga/LlamaFactory · error · ValueError
A placeholder is required in the string formatter.
Error message
A placeholder is required in the string formatter.
What it means
StringFormatter.__post_init__ requires at least one string slot matching the {{identifier}} placeholder regex; otherwise it raises ValueError. Since StringFormatter.apply() works purely by substituting {{name}} patterns, a formatter with no placeholder would silently drop all example content.
Source
Thrown at src/llamafactory/data/formatter.py:69
if has_placeholder:
raise ValueError("Empty formatter should not contain any placeholder.")
@override
def apply(self, **kwargs) -> SLOTS:
return self.slots
@dataclass
class StringFormatter(Formatter):
def __post_init__(self):
has_placeholder = False
for slot in filter(lambda s: isinstance(s, str), self.slots):
if re.search(r"\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}", slot):
has_placeholder = True
if not has_placeholder:
raise ValueError("A placeholder is required in the string formatter.")
@override
def apply(self, **kwargs) -> SLOTS:
elements = []
for slot in self.slots:
if isinstance(slot, str):
for name, value in kwargs.items():
if not isinstance(value, str):
raise RuntimeError(f"Expected a string, got {value}")
slot = slot.replace("{{" + name + "}}", value, 1)
elements.append(slot)
elif isinstance(slot, (dict, set)):
elements.append(slot)
else:
raise RuntimeError(f"Input must be string, set[str] or dict[str, str], got {type(slot)}.")
return elementsView on GitHub (pinned to f28afaf635)
Solutions
- Add the intended placeholder, e.g. {{query}} for alpaca-style or {{content}} for sharegpt-style slots.
- Ensure the placeholder is a valid identifier (letters/digits/underscore, not starting with a digit, no spaces).
- If the slot is truly constant, use EmptyFormatter instead.
Example fix
# before
StringFormatter(slots=["Human: question\nAssistant:"])
# after
StringFormatter(slots=["Human: {{query}}\nAssistant:"]) Defensive patterns
Strategy: validation
Validate before calling
import re
ph = any(re.search(r"\{\{[a-zA-Z_][a-zA-Z0-9_]*\}\}", s) for s in slots if isinstance(s, str))
if formatter_cls is StringFormatter:
assert ph, "StringFormatter needs at least one valid {{identifier}} placeholder" Prevention
- Use identifier-style placeholder names matching dataset columns (query, response, content...).
- Add a template-definition unit test to catch formatter misuse before training.
When it happens
Trigger: Registering a custom template with StringFormatter(slots=["User asked something."]) — literal text with no {{query}}/{{content}} token; also placeholders with invalid identifier characters ({{user query}} with a space, {{1}}) do not count because the regex requires [a-zA-Z_][a-zA-Z0-9_]*.
Common situations: Hand-written custom templates; placeholders renamed to non-identifier forms during dataset schema changes; copy-paste where {{}} got stripped by templating tools.
Related errors
- Empty formatter should not contain any placeholder.
- Expected a string, got {value}
- This model does not support image input. Please check whethe
- This model does not support video input. Please check whethe
- This model does not support audio input. Please check whethe
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/38a589a4012e172d.
Report an issue: GitHub.