hiyouga/LlamaFactory · error · ValueError
`save_epochs` is not supported with `dynamic_batching`; use
Error message
`save_epochs` is not supported with `dynamic_batching`; use `save_steps` instead.
What it means
v1 `TrainingArguments.__post_init__` rejects `save_epochs` together with `batching_strategy: dynamic_batching`. Dynamic batching is step-driven and never computes epoch boundaries, so epoch-conditional checkpointing is meaningless; `save_steps` must be used for periodic checkpoints instead.
Source
Thrown at src/llamafactory/v1/config/training_args.py:198
except ImportError:
pass
# The optimizer learning rate has a single source of truth: ``learning_rate``.
# Propagate it into ``optim_config["lr"]`` so optimizer plugins (e.g. Muon) pick it up
# via ``optim_config.get("lr")`` without each plugin needing a separate ``learning_rate`` arg.
if self.optim_config is not None:
if "lr" in self.optim_config:
logger.warning_rank0(
"`optim_config.lr` is overridden by `learning_rate`; set the learning rate via "
"`learning_rate` instead and remove `lr` from `optim_config`."
)
self.optim_config["lr"] = self.learning_rate
if str(self.batching_strategy) == str(BatchingStrategy.DYNAMIC_BATCHING):
if self.max_steps is None or self.max_steps <= 0:
raise ValueError("`dynamic_batching` requires `max_steps` because it is step-driven.")
if self.save_epochs is not None:
raise ValueError("`save_epochs` is not supported with `dynamic_batching`; use `save_steps` instead.")
View on GitHub (pinned to f28afaf635)
Solutions
- Delete `save_epochs` and set `save_steps` (e.g. `save_steps: 500`)
- If epoch checkpoints are a hard requirement, switch back to a non-dynamic batching strategy and use `max_steps`/`epochs` normally
Example fix
# before (yaml) training: batching_strategy: dynamic_batching max_steps: 1000 save_epochs: 1 # after (yaml) training: batching_strategy: dynamic_batching max_steps: 1000 save_steps: 500
Defensive patterns
Strategy: validation
Validate before calling
def validate_checkpointing(cfg: dict) -> None:
if str(cfg.get("batching_strategy", "")) == "dynamic_batching" and cfg.get("save_epochs") is not None:
raise SystemExit("use save_steps with dynamic_batching, not save_epochs") Prevention
- Standardize on save_steps for all step-driven runs
- Config lint: forbid save_epochs whenever batching_strategy is dynamic_batching
- When porting epoch-based configs, audit every `*_epochs` key
When it happens
Trigger: Configuring `batching_strategy: dynamic_batching` plus a non-null `save_epochs` in the v1 training args.
Common situations: Copying a checkpointing block (`save_epochs: 1`) from an epoch-based config into a dynamic-batching run.
Related errors
- `dynamic_batching` requires `max_steps` because it is step-d
- `padding_free` requires `flash_attn: flash_attention_2`.
- world_size ({helper.get_world_size()}) must be divisible by
- mp_replicate_size * mp_shard_size must equal to world_size,
- world_size ({helper.get_world_size()}) must be divisible by
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/d0eb236195b875c6.
Report an issue: GitHub.