hiyouga/LlamaFactory · error · RuntimeError
Input must be string, set[str] or dict[str, str], got {type(
Error message
Input must be string, set[str] or dict[str, str], got {type(slot)}. What it means
Thrown by StringFormatter.apply while building prompt elements from a template's slots. Every entry in a formatter's `slots` list must be a plain string, a set of strings (choice of stop tokens), or a dict[str, str]; any other Python type reaches the else-branch and raises this RuntimeError. It almost always indicates a malformed custom template registered in data/template.py or a programmatic Template construction with a non-conforming slot.
Source
Thrown at src/llamafactory/data/formatter.py:85
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 elements
@dataclass
class FunctionFormatter(StringFormatter):
def __post_init__(self):
super().__post_init__()
self.tool_utils = get_tool_utils(self.tool_format)
@override
def apply(self, **kwargs) -> SLOTS:
content: str = kwargs.pop("content")
thought_words = kwargs.pop("thought_words", None)
tool_call_words = kwargs.pop("tool_call_words", None)
def _parse_functions(json_content: str) -> list["FunctionCall"]:
try:View on GitHub (pinned to f28afaf635)
Solutions
- Inspect the template definition referenced by your `template` config value and check every element of each formatter's slots: they must be str, set[str], or dict[str, str].
- If you construct a Template in code, validate slots before registration and wrap non-string special tokens as a set, e.g. slots=['user: {{content}} ', {'eos_token'}].
- Switch to a known-good built-in template to confirm the error comes from your custom template, then re-apply your changes incrementally.
- Upgrade to the latest LlamaFactory in case the template API changed between versions.
Example fix
# before
TEMPLATES["my_tpl"] = Template(
format_slots=["user: {{content}}", ["\n", "\n\n"]], # list is invalid
)
# after
TEMPLATES["my_tpl"] = Template(
format_slots=["user: {{content}} ", {"eos_token"}], # str or set[str]/dict[str, str] only
) Defensive patterns
Strategy: type-guard
Validate before calling
from llamafactory.data.formatter import StringFormatter
def valid_slots(formatter) -> bool:
return all(
isinstance(s, str) or (isinstance(s, (set, dict)))
for f in (formatter,) if hasattr(f, "slots")
for s in f.slots
) Type guard
def is_valid_slot(slot: object) -> bool:
if isinstance(slot, str):
return True
if isinstance(slot, set):
return all(isinstance(x, str) for x in slot)
if isinstance(slot, dict):
return all(isinstance(k, str) and isinstance(v, str) for k, v in slot.items())
return False Try / catch
try:
elements = formatter.apply(**kwargs)
except RuntimeError as e:
if "Input must be string" in str(e):
raise ValueError(f"Malformed template slots in {formatter}") from e
raise Prevention
- Register custom templates in a single reviewed module and unit-test slot types.
- Reuse built-in templates unless a custom one is truly required.
- After upgrading LlamaFactory, re-run a 1-sample preprocessing smoke test before full runs.
When it happens
Trigger: Registering a custom template whose formatter slots contain a non-str/set/dict value (e.g. a list, tuple, int, or None), or constructing a StringFormatter/Template object directly with invalid slot types. Also triggered by a plugin/template that programmatically appends unsupported objects to slots.
Common situations: Users copying a template definition from an older LlamaFactory version or another project where slot conventions differed; passing a tokenizer-produced list or an int (e.g. token id) where a string slot is expected; typos when hand-writing TEMPLATES entries.
Related errors
- Empty formatter should not contain any placeholder.
- A placeholder is required in the string formatter.
- Invalid JSON format in function message: {str([content])}.
- Invalid JSON format in tool description: {str([content])}.
- Cannot find valid samples, check `data/README.md` for the da
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/c75a4c2f34efe816.
Report an issue: GitHub.