hiyouga/LlamaFactory · error · ValueError
YAML config must be a dictionary mapping tokens to descripti
Error message
YAML config must be a dictionary mapping tokens to descriptions. Got: {type(token_descriptions)} What it means
Raised in ModelArguments.__post_init__ (model_args.py:224) when new_special_tokens_config points to a YAML file whose top-level structure is not a mapping of token -> description. The config is loaded with OmegaConf and converted with to_container; if the result is a list, scalar, or null (e.g. the file contains only a '- token' list or a bare string), the isinstance(dict) check fails and this ValueError is raised during argument parsing.
Source
Thrown at src/llamafactory/hparams/model_args.py:224
def __post_init__(self):
if self.model_name_or_path is None:
raise ValueError("Please provide `model_name_or_path`.")
if self.adapter_name_or_path is not None: # support merging multiple lora weights
self.adapter_name_or_path = [path.strip() for path in self.adapter_name_or_path.split(",")]
if self.add_tokens is not None: # support multiple tokens
self.add_tokens = [token.strip() for token in self.add_tokens.split(",")]
# Process special tokens with priority: new_special_tokens_config > add_special_tokens
if self.new_special_tokens_config is not None:
# Priority 1: Load from YAML config (extracts both tokens and descriptions)
try:
cfg = OmegaConf.load(self.new_special_tokens_config)
token_descriptions = OmegaConf.to_container(cfg)
if not isinstance(token_descriptions, dict):
raise ValueError(
f"YAML config must be a dictionary mapping tokens to descriptions. "
f"Got: {type(token_descriptions)}"
)
# Extract token list from config keys
extracted_tokens = list(token_descriptions.keys())
# Warn if both are set
if self.add_special_tokens is not None:
logger.warning_rank0(
"Both 'new_special_tokens_config' and 'add_special_tokens' are set. "
f"Using tokens from config: {extracted_tokens}"
)
# Override add_special_tokens with extracted tokens (as list)
self.add_special_tokens = extracted_tokens
# Store descriptions internally for later use (internal attribute)View on GitHub (pinned to f28afaf635)
Solutions
- Rewrite the YAML as a mapping: each top-level key is the token string, its value the description
- Example: '<|im_start|>': 'start of turn' as top-level entries, no leading dashes
- If you only need tokens without descriptions, use the simpler add_special_tokens: '<tok1>,<tok2>' comma-separated string instead
Example fix
# before (specials.yaml) - <|im_start|> - <|im_end|> # after (specials.yaml) '<|im_start|>': 'start of turn' '<|im_end|>': 'end of turn'
Defensive patterns
Strategy: type-guard
Validate before calling
from omegaconf import OmegaConf cfg_doc = OmegaConf.to_container(OmegaConf.load(path)) assert isinstance(cfg_doc, dict), 'special tokens YAML must be a token->description mapping'
Type guard
def is_token_mapping(v: object) -> bool:
return isinstance(v, dict) and all(isinstance(k, str) for k in v) Try / catch
try:
args = ModelArguments(**cfg)
except ValueError as e:
if 'YAML config must be a dictionary' in str(e):
rewrite_list_to_mapping(path) # '- tok' -> "'tok': desc"
args = ModelArguments(**cfg)
else:
raise Prevention
- Token-only needs: use add_special_tokens comma string instead of the config file
- Keep one canonical example mapping file in the repo and diff against it
When it happens
Trigger: new_special_tokens_config: specials.yaml where specials.yaml contains a YAML list of tokens or plain text instead of key: value pairs; an empty YAML file (to_container gives None); a JSON file whose top level is an array.
Common situations: Users writing a token list (the intuitive format) instead of a mapping; reusing the same file for add_special_tokens (comma string) and the config variant; hand-editing that accidentally deletes the mapping structure.
Related errors
- `virtual_pipeline_model_parallel_size` must be >= 1 when set
- `sequence_parallel` requires `tensor_model_parallel_size` >
- Please provide `model_name_or_path`.
- `image_max_pixels` cannot be smaller than `image_min_pixels`
- `video_max_pixels` cannot be smaller than `video_min_pixels`
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/8211a01e9eb9cfc3.
Report an issue: GitHub.