unslothai/unsloth · error · ValueError
learning_rate is required
Error message
learning_rate is required
What it means
Raised by the _parse_lr field parser used for learning_rate in TrainingStartRequest. learning_rate has no default, so passing None (or omitting it when the client schema does not mark it optional) reaches the parser and fails immediately with this dedicated message rather than a generic 'field required' error. The parser also rejects bools, non-numeric values, non-positive values, and values >= 1.0 in subsequent checks.
Source
Thrown at studio/backend/models/training.py:85
alias = "useIamRole",
description = "Use IAM role credentials instead of access keys",
)
@model_validator(mode = "after")
def _check_credentials(self) -> "S3Config":
# Require either IAM role auth or a full key pair so credentials are never half-configured.
if not self.use_iam_role and not (self.access_key_id and self.secret_access_key):
raise ValueError(
"s3_config requires either use_iam_role=True or both "
"access_key_id and secret_access_key"
)
return self
def _parse_lr(v: Any) -> float:
"""Parse learning_rate as a positive float strictly below _MAX_LR_VALUE."""
if v is None:
raise ValueError("learning_rate is required")
if isinstance(v, bool):
raise ValueError("learning_rate must be a number, not a bool")
try:
lr = float(v)
except (TypeError, ValueError):
raise ValueError(f"learning_rate must be parseable as float (got {v!r})")
if not (lr > 0.0):
raise ValueError(f"learning_rate must be > 0 (got {lr!r}); typical range is 1e-6 .. 1e-3")
if lr >= _MAX_LR_VALUE:
raise ValueError(
f"learning_rate must be < 1.0 (got {lr!r}); values that large always diverge training"
)
return lr
class TrainingStartRequest(BaseModel):
"""Request schema for starting training"""
View on GitHub (pinned to 203007d190)
Solutions
- Set an explicit learning_rate in the request; typical values are 1e-6 to 1e-3 (e.g. 2e-5 for LoRA fine-tuning).
- Make the field required in your client schema so nulls cannot be serialized.
- If the LR should come from a preset/config file, ensure that file actually contains the key before building the request.
Example fix
// before
body = { model_name, hf_dataset, learning_rate: form.lr } // form.lr is null
// after
body = { model_name, hf_dataset, learning_rate: form.lr ?? 2e-5 } Defensive patterns
Strategy: validation
Validate before calling
def has_learning_rate(body: dict) -> bool:
return body.get("learning_rate") is not None Type guard
function hasLr(body: { learning_rate?: number | null }): boolean {
return typeof body.learning_rate === 'number';
} Prevention
- Make learning_rate a required number in client types
- Default blank UI fields to a sane value (2e-5) instead of null
- Reject null in the request builder
When it happens
Trigger: POST a training start request with "learning_rate": null, or a request body that omits learning_rate where the client-side serializer explicitly sends null (common when a typed client has learning_rate?: number).
Common situations: A form/UI where the LR field is optional and submits null when blank; copying a config template that used a scheduler to derive LR; migrating from an API version where learning_rate had a default; JSON serializers that emit null for unset optional fields.
Related errors
- learning_rate must be parseable as float (got {v!r})
- learning_rate must be > 0 (got {lr!r}); typical range is 1e-
- learning_rate must be < 1.0 (got {lr!r}); values that large
- learning_rate must be a number, got {self.learning_rate!r}
- learning_rate must be > 0
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/ff0feb6b15995e8a.
Report an issue: GitHub.