unslothai/unsloth · error · ValueError
Unsloth MLX: max_grad_value={max_grad_value} must be finite
Error message
Unsloth MLX: max_grad_value={max_grad_value} must be finite and >= 0 (0 or None disables elementwise clipping). What it means
Raised by the Unsloth MLX training worker when the config value max_grad_value is negative or non-finite (NaN or +/-inf). max_grad_value controls elementwise gradient clipping in the MLX trainer; 0 or None disables it, so any other value must be a finite float >= 0. This is a re-validation in the worker because the worker can be called directly, bypassing the normalization that training.py performs on the main path.
Source
Thrown at studio/backend/core/training/worker.py:3014
# ── 6. Create trainer ──
raw_eval_steps = config.get("eval_steps", 0)
if evaluation_enabled(raw_eval_steps):
eval_steps_value = float(raw_eval_steps)
else:
eval_steps_value = 0.0
if 0 < eval_steps_value < 1:
eval_steps_val = max(1, int(eval_steps_value * max_steps))
else:
eval_steps_val = int(eval_steps_value)
# Re-validate for direct worker callers; training.py normalizes the main path.
max_grad_norm = _resolve_mlx_max_grad_norm(config.get("max_grad_norm"))
max_grad_value = config.get("max_grad_value")
if max_grad_value is not None:
max_grad_value = float(max_grad_value)
if max_grad_value < 0 or not math.isfinite(max_grad_value):
raise ValueError(
f"Unsloth MLX: max_grad_value={max_grad_value} must be finite and >= 0 "
"(0 or None disables elementwise clipping)."
)
max_grad_leaf_norm = config.get("max_grad_leaf_norm")
if max_grad_leaf_norm is not None:
max_grad_leaf_norm = float(max_grad_leaf_norm)
if max_grad_leaf_norm < 0 or not math.isfinite(max_grad_leaf_norm):
raise ValueError(
f"Unsloth MLX: max_grad_leaf_norm={max_grad_leaf_norm} must be finite and >= 0 "
"(0 or None disables proportional leaf-norm clipping)."
)
weight_decay = config.get("weight_decay", 0.001)
weight_decay = 0.001 if weight_decay is None else float(weight_decay)
mlx_config_kwargs = dict(
per_device_train_batch_size = batch_size,
gradient_accumulation_steps = grad_accum,
max_steps = max_steps,View on GitHub (pinned to 203007d190)
Solutions
- Set max_grad_value to 0 or remove it (None) if you want elementwise clipping disabled, or to a finite positive float like 1.0.
- If you call the worker directly, normalize the value before dispatch (mirror what training.py does) so NaN/negative sentinels are converted to None.
- Check the upstream config source (UI, YAML, API payload) for NaN-inducing values such as .nan, float('inf'), or -1 sentinels and fix them there.
Example fix
# before
config = {"max_grad_value": -1} # raises ValueError
# after
config = {"max_grad_value": None} # disables elementwise clipping Defensive patterns
Strategy: validation
Validate before calling
import math
def valid_max_grad_value(value):
return value is None or (isinstance(value, (int, float)) and math.isfinite(value) and value >= 0)
if not valid_max_grad_value(config.get("max_grad_value")):
config["max_grad_value"] = None # or raise your own clearer error early Type guard
def is_valid_max_grad_value(v) -> bool:
return v is None or (isinstance(v, (int, float)) and not isinstance(v, bool) and math.isfinite(v) and v >= 0) Try / catch
try:
run_training(config)
except ValueError as e:
if "max_grad_value" in str(e):
config["max_grad_value"] = None
run_training(config)
else:
raise Prevention
- Validate numeric hyperparameters at the API/UI boundary before they reach the training worker.
- Never use -1 or 1e9 as an 'off' sentinel for clipping fields; use None or 0.
- Reject NaN/inf early wherever config values are computed (sweeps, YAML loads).
When it happens
Trigger: Calling the MLX training worker with config['max_grad_value'] set to a negative number, NaN, or inf (e.g. from a math expression that overflowed, a string parsed later, or -1 used as a 'disable' sentinel). Passing 0 or None does NOT trigger it; passing a finite positive float does not either.
Common situations: Users copy a PyTorch-style config where -1 or 1e9 means 'off'; a UI/API forwards an empty string that converts to NaN; a YAML config has .nan or .inf; hyperparameter sweeps generate out-of-range values.
Related errors
- Unsloth MLX: max_grad_leaf_norm={max_grad_leaf_norm} must be
- dataset_streaming is not yet supported on Apple Silicon (MLX
- '{family_name}' needs diffusers ({pipeline_class}), which th
- '{family_name}' needs diffusers ({pipeline_class}), but this
- Unsloth MLX: use_adapter must be None, True, False, or a str
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/84f3f6b1c0161dd8.
Report an issue: GitHub.