unslothai/unsloth · error · ValueError
num_frames must be positive, got {num_frames}.
Error message
num_frames must be positive, got {num_frames}. What it means
Raised by h3_align_num_frames() when num_frames is less than 1. The function's job is to snap a frame count UP to the next value of the form 17*n + 5 that the MiniMax-H3 video VAE can encode, and that arithmetic is meaningless for zero or negative inputs. It guards a pure integer precondition before any alignment loop runs.
Source
Thrown at studio/backend/core/training/diffusion_h3_clips.py:90
# This is deliberately far below the 5 s floor MiniMax-H3 *generates* at, and the trade is
# explicit: the packed sequence is quadratic in its own length through the full self-attention,
# so at the released 768-short-edge canvas a 5 s clip is ~38k rows and a 22-frame clip is ~7k.
# Training at the native canvas on short clips keeps the SPATIAL statistics -- which is what a
# style LoRA learns -- exactly on distribution, and only shortens the temporal extent; training
# a 5 s clip at a canvas small enough to fit would put every spatial statistic off distribution
# instead. The temporal rotary grid of a 22-frame clip is a strict PREFIX of the grid of a
# generated one (``_temporal_position_grid`` starts at the same origin with the same spacing),
# so no row sits at a coordinate the model never visits.
H3_TRAIN_NUM_FRAMES = H3_FRAMES_PER_CHUNK + H3_LATENTS_PER_CHUNK
_VIDEO_EXTS = {".mp4", ".mov", ".mkv", ".webm", ".m4v", ".avi"}
_CAPTION_EXTS = (".txt", ".caption")
def h3_align_num_frames(num_frames: int) -> int:
"""Snap a frame count UP to the next ``17 * n + 5`` the video VAE can encode."""
if num_frames < 1:
raise ValueError(f"num_frames must be positive, got {num_frames}.")
while num_frames % H3_FRAMES_PER_CHUNK != H3_LATENTS_PER_CHUNK:
num_frames += 1
return num_frames
def h3_video_latent_frames(num_frames: int) -> int:
"""Latent frames the video VAE produces for an aligned frame count: ``5 * n + 2``."""
if num_frames % H3_FRAMES_PER_CHUNK != H3_LATENTS_PER_CHUNK:
raise ValueError(
f"num_frames must be of the form {H3_FRAMES_PER_CHUNK} * n + {H3_LATENTS_PER_CHUNK}, "
f"got {num_frames}."
)
return (num_frames - H3_LATENTS_PER_CHUNK) // H3_FRAMES_PER_CHUNK * H3_LATENTS_PER_CHUNK + 2
def h3_audio_latent_count(num_frames: int) -> int:
"""Audio latents (per channel) covering ``num_frames`` frames at 24 fps / 40 latents per s."""
return int(round(num_frames / H3_FPS * H3_AUDIO_LATENTS_PER_SECOND))View on GitHub (pinned to 203007d190)
Solutions
- Pass a positive frame count; for H3 training use H3_TRAIN_NUM_FRAMES (22) or another 17*n+5 value.
- Trace where the zero/negative value originates (form default, subtraction, parse) and fix the producer.
- Validate with num_frames >= 1 at your config boundary before calling the alignment helper.
Example fix
# before n = h3_align_num_frames(max_frames - trim) # trim == max_frames -> 0 # after n = h3_align_num_frames(max(1, max_frames - trim))
Defensive patterns
Strategy: validation
Validate before calling
def frames_alignable(num_frames: int) -> bool:
return isinstance(num_frames, int) and num_frames >= 1 Prevention
- Validate num_frames >= 1 at the config boundary (UI/API) before it reaches alignment helpers.
- Prefer using the H3_TRAIN_NUM_FRAMES constant instead of computing counts by hand.
When it happens
Trigger: Calling h3_align_num_frames(0) or with a negative count; deriving num_frames from user input, a clip probe, or a subtraction (e.g. num_frames - offset) that underflows to zero.
Common situations: Default-initializing num_frames to 0 in a form and passing it through unvalidated; slicing logic computing an empty window; a misparsed CLI argument.
Related errors
- num_frames must be of the form {H3_FRAMES_PER_CHUNK} * n + {
- transformer_quant '{requested_scheme}' is unavailable for '{
- '{Path(gguf_filename or '').name}' is the {picked} partition
- '{fam.name}' is a dual-expert model: a single {kind} file co
- The source image has no usable aspect ratio ({aspect_width}x
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/eaa55ee90e5e5676.
Report an issue: GitHub.