sgl-project/sglang · error · ValueError
nframes should in interval [{FRAME_FACTOR}, {total_frames}],
Error message
nframes should in interval [{FRAME_FACTOR}, {total_frames}], but got {nframes}. What it means
Raised by ernie45_vl.smart_nframes after clamping and floor-rounding the target frame count to FRAME_FACTOR: the result fell outside [FRAME_FACTOR, total_frames]. Because floor_by_factor can drop nframes below FRAME_FACTOR (e.g. total_frames=7, factor=4, clamp gives 4 but floor of an odd count can yield 0 in degenerate cases), or the video has fewer frames than FRAME_FACTOR, no valid frame count exists.
Source
Thrown at python/sglang/srt/multimodal/processors/ernie45_vl.py:167
"fps" in ele and "nframes" in ele
), "Only accept either `fps` or `nframes`"
if "nframes" in ele:
nframes = round_by_factor(ele["nframes"], FRAME_FACTOR)
else:
fps = ele.get("fps", FPS)
min_frames = ceil_by_factor(ele.get("min_frames", FPS_MIN_FRAMES), FRAME_FACTOR)
max_frames = floor_by_factor(
ele.get("max_frames", min(FPS_MAX_FRAMES, total_frames)), FRAME_FACTOR
)
nframes = total_frames / video_fps * fps
if nframes > total_frames:
logger.warning(
f"smart_nframes: nframes[{nframes}] > total_frames[{total_frames}]"
)
nframes = min(min(max(nframes, min_frames), max_frames), total_frames)
nframes = floor_by_factor(nframes, FRAME_FACTOR)
if not (FRAME_FACTOR <= nframes and nframes <= total_frames):
raise ValueError(
f"nframes should in interval [{FRAME_FACTOR}, {total_frames}], but got {nframes}."
)
return nframes
# process video, qwen-specific
async def preprocess_video(
vr,
image_factor: int = IMAGE_FACTOR,
) -> torch.Tensor:
total_frames, video_fps = len(vr), vr.get_avg_fps()
nframes = smart_nframes({}, total_frames=total_frames, video_fps=video_fps)
idx = np.linspace(0, total_frames - 1, num=nframes, dtype=np.int64)
idx = np.unique(idx)
video_np = vr.get_batch(idx).asnumpy()
video = torch.from_numpy(video_np).pin_memory()
video = video.permute(0, 3, 1, 2) # Convert to TCHW formatView on GitHub (pinned to 0132848349)
Solutions
- Skip or reject videos with total_frames < FRAME_FACTOR before preprocessing
- Ensure max_frames >= FRAME_FACTOR and is a multiple of the frame factor
- For short clips, pad or duplicate frames so total_frames >= FRAME_FACTOR
Example fix
# before
out = processor.preprocess_video(video_list, ...) # video decodes to 1 frame
# after
if n_total < FRAME_FACTOR:
raise SkipSample(f'video too short: {n_total} frames')
out = processor.preprocess_video(video_list, ...) Defensive patterns
Strategy: validation
Validate before calling
total = count_frames(path)
if total < FRAME_FACTOR: # 2 for ernie45
raise SkipSample(f'video too short: {total} frames') Type guard
def has_enough_frames(path: str, minimum: int = 2) -> bool:
return count_frames(path) >= minimum Try / catch
try:
out = preprocess_video(v, ...)
except ValueError as e:
if 'nframes should in interval' in str(e):
mark_video_corrupt(v); continue
raise Prevention
- Pre-scan video duration/frames before batching
- Keep max_frames a multiple of FRAME_FACTOR and >= it
- Drop single-frame/corrupt files at dataset build time
When it happens
Trigger: Calling preprocess_video on a video whose total decoded frames < FRAME_FACTOR (2); FPS-based nframes computed from a very short clip (e.g. total_video_seconds*fps < 2); nframes clamped to max_frames that is itself below factor.
Common situations: Very short or corrupt video files that decode to 1 frame; metadata claiming a duration the decoder doesn't deliver; custom max_frames set to 1.
Related errors
- encounter invalid h_bar: {h_bar}, w_bar: {w_bar}
- cos/sin shape does not cover image tokens and head_dim
- Unsupported image type: {type(image)}
- QwenImageEditPlus expects either one shared condition image
- QwenImage RoPE text cache overflow before denoising: require
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/ce70890def765938.
Report an issue: GitHub.