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

  1. 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].
  2. 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'}].
  3. Switch to a known-good built-in template to confirm the error comes from your custom template, then re-apply your changes incrementally.
  4. 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

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


AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14). Data as JSON: /api/errors/c75a4c2f34efe816. Report an issue: GitHub.