hiyouga/LlamaFactory · error · ValueError
`dynamic_batching` requires `max_steps` because it is step-d
Error message
`dynamic_batching` requires `max_steps` because it is step-driven.
What it means
In v1 `TrainingArguments.__post_init__`, choosing `batching_strategy: dynamic_batching` requires `max_steps` to be a positive integer because dynamic batching has no fixed epoch boundary — training length is driven purely by optimizer steps. Without `max_steps` the trainer could not know when to stop or schedule.
Source
Thrown at src/llamafactory/v1/config/training_args.py:196
register_deepspeed_dist_config(self.dist_config)
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
- Set an explicit positive `max_steps` appropriate for your token budget (e.g. `max_steps: 1000`)
- Replace `epochs`-based stopping with `max_steps` when using dynamic batching
- If you need epoch semantics, keep a static/padding strategy instead of `dynamic_batching`
Example fix
# before (yaml) training: batching_strategy: dynamic_batching epochs: 3 # after (yaml) training: batching_strategy: dynamic_batching max_steps: 1000
Defensive patterns
Strategy: validation
Validate before calling
def validate_dynamic_batching(cfg: dict) -> None:
if str(cfg.get("batching_strategy", "")) == "dynamic_batching":
steps = cfg.get("max_steps")
if steps is None or steps <= 0:
raise SystemExit("dynamic_batching requires positive max_steps") Prevention
- Treat dynamic batching as step-driven: always pair it with max_steps
- Lint configs for (dynamic_batching, epochs) and (dynamic_batching, missing max_steps) combos
- Document the step budget next to the batching strategy in team templates
When it happens
Trigger: Setting `batching_strategy: dynamic_batching` in v1 training args while `max_steps` is None (default) or <= 0, typically because the config relies on `epochs` instead.
Common situations: Switching an epoch-based config to dynamic batching without adding a step budget; setting `max_steps: -1` (HF convention for 'unset') which fails the <= 0 check.
Related errors
- `save_epochs` is not supported with `dynamic_batching`; use
- `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/e95bbdc55a6ecd1a.
Report an issue: GitHub.