docling-project/docling · error · ValueError
max_frames must be > 0 when set
Error message
max_frames must be > 0 when set
What it means
ValueError raised by FixedIntervalFrameSampler.__init__ in docling/utils/video_frame_sampling.py when max_frames is provided and is <= 0. max_frames caps the number of extracted frames to bound memory and runtime; None means unlimited, so zero or negative values are treated as configuration errors rather than as 'no frames'.
Source
Thrown at docling/utils/video_frame_sampling.py:288
frames: list[tuple[float, Image.Image]] = []
for i in range(count):
chunk = buf[i * frame_bytes : (i + 1) * frame_bytes]
frames.append((i / fps, Image.frombytes("RGB", (size, size), chunk)))
return frames
class FixedIntervalFrameSampler:
"""Sample one frame every ``interval_seconds`` from time zero."""
def __init__(
self,
interval_seconds: float = 10.0,
max_frames: int | None = None,
):
if interval_seconds <= 0:
raise ValueError("interval_seconds must be > 0")
if max_frames is not None and max_frames <= 0:
raise ValueError("max_frames must be > 0 when set")
self.interval_seconds = interval_seconds
self.max_frames = max_frames
def sample(self, video_path: Path) -> list[VideoFrame]:
_require_ffmpeg()
duration = _probe_duration(video_path)
frames: list[VideoFrame] = []
t = 0.0
# If duration is unknown (0.0), rely on extraction returning None at EOF.
while duration == 0.0 or t < duration:
if self.max_frames is not None and len(frames) >= self.max_frames:
break
image = _extract_frame(video_path, t)
if image is None:
break
frames.append(VideoFrame(timestamp=t, image=image))
t += self.interval_secondsView on GitHub (pinned to 61d76f1ff3)
Solutions
- Omit max_frames or pass None when you want no cap; pass a positive int such as max_frames=100 to cap extraction.
- Normalize configuration inputs: convert 0/negative to None if 'unlimited' was intended: max_frames = value or None.
- Validate derived budgets before construction and surface a clear error if the budget cannot afford at least one frame.
Example fix
# before sampler = FixedIntervalFrameSampler(max_frames=cfg.max_frames) # cfg default 0 -> ValueError # after cap = cfg.max_frames if isinstance(cfg.max_frames, int) and cfg.max_frames > 0 else None sampler = FixedIntervalFrameSampler(max_frames=cap)
Defensive patterns
Strategy: validation
Validate before calling
cap = max_frames if isinstance(max_frames, int) and max_frames > 0 else None sampler = FixedIntervalFrameSampler(interval_seconds=10.0, max_frames=cap)
Type guard
def is_valid_frame_cap(value: int | None) -> bool:
return value is None or value > 0 Prevention
- Use None (not 0) to mean 'unlimited frames' in configs and CLIs.
- Map sentinel values like 0 or -1 to None before constructing samplers.
- Validate derived budgets so a cap of 0 fails loudly in your config layer with a better message.
When it happens
Trigger: Explicitly passing max_frames=0 or a negative int, e.g. FixedIntervalFrameSampler(interval_seconds=5, max_frames=0). Passing max_frames=None is valid (unlimited).
Common situations: CLI/config plumbing where an unset integer option defaults to 0 instead of None; computing max_frames as a budget-derived value (frames = budget // cost) that evaluates to 0 or negative; misreading 0 as 'no cap' when the API uses None for that.
Related errors
- interval_seconds must be > 0
- probe_fps must be > 0
- prominence must be >= 0
- min_scene_duration_seconds must be >= 0
- Cannot convert Box Note with hash {self.document_hash}: no '
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/919436e7137fc92b.
Report an issue: GitHub.