{"record":{"id":"eaa55ee90e5e5676","repo":"unslothai/unsloth","slug":"num-frames-must-be-positive-got-num-frames","errorCode":null,"errorMessage":"num_frames must be positive, got {num_frames}.","messagePattern":"num_frames must be positive, got (.+?)\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/training/diffusion_h3_clips.py","lineNumber":90,"sourceCode":"# This is deliberately far below the 5 s floor MiniMax-H3 *generates* at, and the trade is\n# explicit: the packed sequence is quadratic in its own length through the full self-attention,\n# so at the released 768-short-edge canvas a 5 s clip is ~38k rows and a 22-frame clip is ~7k.\n# Training at the native canvas on short clips keeps the SPATIAL statistics -- which is what a\n# style LoRA learns -- exactly on distribution, and only shortens the temporal extent; training\n# a 5 s clip at a canvas small enough to fit would put every spatial statistic off distribution\n# instead. The temporal rotary grid of a 22-frame clip is a strict PREFIX of the grid of a\n# generated one (``_temporal_position_grid`` starts at the same origin with the same spacing),\n# so no row sits at a coordinate the model never visits.\nH3_TRAIN_NUM_FRAMES = H3_FRAMES_PER_CHUNK + H3_LATENTS_PER_CHUNK\n\n_VIDEO_EXTS = {\".mp4\", \".mov\", \".mkv\", \".webm\", \".m4v\", \".avi\"}\n_CAPTION_EXTS = (\".txt\", \".caption\")\n\n\ndef h3_align_num_frames(num_frames: int) -> int:\n    \"\"\"Snap a frame count UP to the next ``17 * n + 5`` the video VAE can encode.\"\"\"\n    if num_frames < 1:\n        raise ValueError(f\"num_frames must be positive, got {num_frames}.\")\n    while num_frames % H3_FRAMES_PER_CHUNK != H3_LATENTS_PER_CHUNK:\n        num_frames += 1\n    return num_frames\n\n\ndef h3_video_latent_frames(num_frames: int) -> int:\n    \"\"\"Latent frames the video VAE produces for an aligned frame count: ``5 * n + 2``.\"\"\"\n    if num_frames % H3_FRAMES_PER_CHUNK != H3_LATENTS_PER_CHUNK:\n        raise ValueError(\n            f\"num_frames must be of the form {H3_FRAMES_PER_CHUNK} * n + {H3_LATENTS_PER_CHUNK}, \"\n            f\"got {num_frames}.\"\n        )\n    return (num_frames - H3_LATENTS_PER_CHUNK) // H3_FRAMES_PER_CHUNK * H3_LATENTS_PER_CHUNK + 2\n\n\ndef h3_audio_latent_count(num_frames: int) -> int:\n    \"\"\"Audio latents (per channel) covering ``num_frames`` frames at 24 fps / 40 latents per s.\"\"\"\n    return int(round(num_frames / H3_FPS * H3_AUDIO_LATENTS_PER_SECOND))","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/training/diffusion_h3_clips.py#L72-L108","documentation":"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.","triggerScenarios":"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.","commonSituations":"Default-initializing num_frames to 0 in a form and passing it through unvalidated; slicing logic computing an empty window; a misparsed CLI argument.","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."],"exampleFix":"# before\nn = h3_align_num_frames(max_frames - trim)  # trim == max_frames -> 0\n\n# after\nn = h3_align_num_frames(max(1, max_frames - trim))","handlingStrategy":"validation","validationCode":"def frames_alignable(num_frames: int) -> bool:\n    return isinstance(num_frames, int) and num_frames >= 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["validation","video","minimax-h3","frame-count"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}