unslothai/unsloth · error · ValueError
learning_rate must be > 0
Error message
learning_rate must be > 0
What it means
After successful float coercion, learning_rate must be strictly positive. A zero or negative learning rate would make AdamW a no-op (or diverge), so it is rejected at preflight rather than wasting a GPU-allocated run.
Source
Thrown at studio/backend/core/training/diffusion_train_common.py:1179
try:
cfg_dropout = float(self.cfg_dropout or 0.0)
except (TypeError, ValueError) as exc:
raise ValueError(f"cfg_dropout must be a number, got {self.cfg_dropout!r}") from exc
if not 0.0 <= cfg_dropout <= 1.0:
raise ValueError("cfg_dropout must be between 0 and 1")
weighting_scheme = str(self.weighting_scheme or "none").strip().lower()
if weighting_scheme not in ("none", "bell"):
raise ValueError("weighting_scheme must be one of none / bell")
# A zero/negative gamma would zero out (or invert) the min-SNR weight and silently train on a degenerate loss; None is the documented disable.
if self.snr_gamma is not None and float(self.snr_gamma) <= 0:
raise ValueError("snr_gamma must be > 0, or null to disable min-SNR weighting")
# learning_rate can arrive as a string ("1e-4") from the Studio config path, so coerce it before AdamW sees it.
try:
learning_rate = float(self.learning_rate)
except (TypeError, ValueError) as exc:
raise ValueError(f"learning_rate must be a number, got {self.learning_rate!r}") from exc
if learning_rate <= 0:
raise ValueError("learning_rate must be > 0")
alpha = self.lora_alpha if self.lora_alpha is not None else self.lora_rank
targets = tuple(self.lora_target_modules) or DEFAULT_LORA_TARGETS
# A blank Hub token (the Studio default when none is configured) must load anonymously, not as an explicit empty credential.
token = self.hf_token.strip() if isinstance(self.hf_token, str) else self.hf_token
from core.inference.diffusion_families import (
_is_local_path,
mirror_repo,
prefer_ungated_mirror,
upstream_is_gated,
)
if resolved_family == "sdxl":
fetch_base_model = self.base_model
else:
fetch_base_model = prefer_ungated_mirror(self.base_model, token or None)
# For a GATED upstream and no token, the cache preference has to be overridden: the
# credentials this run lacks are the credentials the fetch needs, so a partial
# snapshot cannot be completed and the start route's HEAD refuses even a completeView on GitHub (pinned to 203007d190)
Solutions
- Set a positive learning rate — LoRA on diffusion models typically uses 1e-4 to 5e-4.
- If a UI produced 0, require the field to be filled before submission rather than defaulting to 0.
Example fix
# before cfg = DiffusionLoraConfig(learning_rate=0) # after cfg = DiffusionLoraConfig(learning_rate=1e-4)
Defensive patterns
Strategy: validation
Validate before calling
lr = float(learning_rate)
if lr <= 0:
raise ValueError('learning_rate must be > 0 (typical LoRA range: 1e-4 to 5e-4)') Prevention
- Never let a slider default of 0 submit; require an explicit value.
- Range-check learning rate against sane bounds (e.g. 1e-7..1e-2) in the UI.
When it happens
Trigger: learning_rate=0, -1e-4, or a string like '0' / '-0.0001'. Also '-0.0', which floats to -0.0 and fails the <= 0 check.
Common situations: Slider defaults at zero submitted without user input; a sign typo; configs templated with an unset placeholder of 0.
Related errors
- cfg_dropout must be between 0 and 1
- learning_rate must be a number, got {self.learning_rate!r}
- learning_rate is required
- learning_rate must be parseable as float (got {v!r})
- learning_rate must be > 0 (got {lr!r}); typical range is 1e-
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/4ee0da6e79733743.
Report an issue: GitHub.