unslothai/unsloth · error · ValueError
'{resolved_family}' trains at a resolution that is a multipl
Error message
'{resolved_family}' trains at a resolution that is a multiple of {_VIDEO_RESOLUTION_MULTIPLE} (its VAE compresses space by that factor); got {self.resolution}. What it means
Raised when a video-family model's training resolution is not a multiple of _VIDEO_RESOLUTION_MULTIPLE (32). Video VAEs compress spatial dimensions by 32 rather than 8, so an off-grid resolution silently changes the latent geometry and produces corrupted/incorrect crops. The validator refuses it before the run starts, while eviction of resident GPU models is still cheap to avoid.
Source
Thrown at studio/backend/core/training/diffusion_train_common.py:1029
if self.train_batch_size < 1:
raise ValueError("train_batch_size must be >= 1")
if self.gradient_accumulation_steps < 1:
raise ValueError("gradient_accumulation_steps must be >= 1")
if self.lora_rank < 1:
raise ValueError("lora_rank must be >= 1")
if self.lora_alpha is not None and self.lora_alpha < 1:
raise ValueError(
"lora_alpha must be >= 1 (a zero/negative alpha scales the adapter to nothing)"
)
if self.resolution < 64 or self.resolution % 8 != 0:
raise ValueError("resolution must be a multiple of 8 and >= 64")
# A video family's VAE compresses space by 32, so an off-grid resolution changes the
# latent geometry silently. Refuse it here, before the GPU models are evicted.
if (
resolved_family in TRAINABLE_VIDEO_FAMILIES
and self.resolution % _VIDEO_RESOLUTION_MULTIPLE != 0
):
raise ValueError(
f"'{resolved_family}' trains at a resolution that is a multiple of "
f"{_VIDEO_RESOLUTION_MULTIPLE} (its VAE compresses space by that factor); "
f"got {self.resolution}."
)
if self.mixed_precision not in ("bf16", "fp16", "no"):
raise ValueError("mixed_precision must be one of bf16 / fp16 / no")
# torch.manual_seed unpacks int64/uint64, so anything wider raises inside the trainer, after eviction. Catch it here.
if not -(2**63) <= int(self.seed) <= 2**64 - 1:
raise ValueError("seed must fit in torch's 64-bit range")
# Refuse fp16 for a bf16-only DiT family up front, before evicting resident models.
if self.mixed_precision == "fp16" and resolved_family in _FORCE_BF16_FAMILIES:
raise ValueError(
f"'{resolved_family}' LoRA training requires bf16: fp16 overflows its fp32 "
f"RoPE / embedder internals. Set mixed precision to bf16."
)
if str(self.lr_scheduler) not in _LR_SCHEDULERS:
raise ValueError(
f"lr_scheduler must be one of {', '.join(sorted(_LR_SCHEDULERS))}; "View on GitHub (pinned to 203007d190)
Solutions
- Set the resolution to a multiple of 32 that is >= 64 (e.g. 512, 576, 640, 768).
- Round up: resolution = ((desired + 31) // 32) * 32.
- When porting a config from image to video training, re-check every resolution field against the 32 grid.
Example fix
# before (image-style bucket, 8-multiple but not 32) config = TrainConfig(resolution=712, ...) # after config = TrainConfig(resolution=736, ...)
Defensive patterns
Strategy: validation
Validate before calling
VIDEO_MULTIPLE = 32
def check_video_resolution(resolution, family) -> int:
r = int(resolution)
if r < 64 or r % 8 != 0:
raise ValueError(f"resolution must be a multiple of 8 and >= 64, got {r}")
if family in TRAINABLE_VIDEO_FAMILIES and r % VIDEO_MULTIPLE != 0:
raise ValueError(f"video family {family} needs resolution % {VIDEO_MULTIPLE} == 0, got {r}")
return r
def snap_video_resolution(r) -> int:
return max(64, ((int(r) + VIDEO_MULTIPLE - 1) // VIDEO_MULTIPLE) * VIDEO_MULTIPLE) Type guard
def is_valid_video_resolution(v, family) -> bool:
try:
r = int(v)
except (TypeError, ValueError):
return False
if r < 64 or r % 8 != 0:
return False
return family not in TRAINABLE_VIDEO_FAMILIES or r % 32 == 0 Try / catch
try:
session.submit_training(config)
except ValueError as e:
if "multiple of" in str(e) and "VAE compresses" in str(e):
config.resolution = snap_video_resolution(config.resolution)
session.submit_training(config)
else:
raise Prevention
- Key your resolution snapping on family: 8-grid for image families, 32-grid for video families.
- Never reuse an image-model bucket list for video training without re-validating.
- Centralize the family -> resolution-multiple mapping in one helper so both validation and UI use it.
When it happens
Trigger: Training a video family (e.g. one of TRAINABLE_VIDEO_FAMILIES such as an Hunyuan/SVD-style DiT) with a resolution that passes the general % 8 check but not % 32 — e.g. 520, 640 is fine, 512+8=520 is not. Configs ported from image (x8) training to video training hit this.
Common situations: Reusing an image-model resolution bucket (e.g. 896 or 712) for a video model; dataset-native resolutions that are multiples of 8 but not 32; assuming the % 8 rule is the only constraint.
Related errors
- resolution must be a multiple of 8 and >= 64
- gradient_accumulation_steps must be >= 1
- base_precision={base_precision!r} trains in bf16 compute; se
- base_precision={base_precision!r} is not validated for train
- Unknown model_kind '{model_kind}'. Expected one of {sorted(_
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/c217b11df7822a40.
Report an issue: GitHub.