affaan-m/ECC · error · ValueError
analyze() needs at least one frame
Error message
analyze() needs at least one frame
What it means
analyze() computes grade statistics from a list of decoded frames and rejects empty input up front, because downstream concatenation and percentile math would produce NaNs or IndexError on an empty stack. It is a defensive guard for callers that skipped or failed frame extraction.
Solutions
- Guard with `if frames:` before calling analyze() and handle the empty case explicitly
- Ensure sample_frames() succeeded and returned a non-empty list before analysis
- If frames may be filtered, raise or log earlier instead of passing an empty list downstream
- Catch ValueError and skip the clip with a warning if empty input is expected sometimes
Example fix
// before
stats = analyze(frames) # ValueError on empty list
// after
if not frames:
raise SkipClip("no frames to analyze")
stats = analyze(frames) Defensive patterns
Strategy: validation
Validate before calling
if not frames:
raise ValueError("no frames extracted; refusing to analyze") Try / catch
try:
stats = analyze(frames)
except ValueError as e:
if "needs at least one frame" in str(e):
log.warning("skipping clip: no frames"); stats = None
else: raise Prevention
- Never call analyze() on a list you have not length-checked
- Handle sample_frames() failures by skipping the clip, not by proceeding with []
- Assert non-empty frames at pipeline stage boundaries
When it happens
Trigger: Calling analyze([]) after sample_frames() returned nothing, after filtering out all frames, or when frame extraction was skipped due to an earlier (swallowed) error.
Common situations: Pipelines that catch the 'decoded zero frames' error and continue with an empty list; masking/filter logic that discards every frame; initializing accumulator lists that never got populated.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- expected (N, 3) pixels, got
- fps must be positive, got
- merge_videos() needs at least one video URL
- nothing to concatenate
- output width and height must be positive
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/760fc0f707811b06.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-distillation/scripts/taste/grade.py:214
populated = [i for i, v in enumerate(raw) if v is not None]
if not populated:
g = [float(a.mean()), float(a.std()), float(b.mean()), float(b.std())]
return [list(g) for _ in range(_N_ZONES)]
out: list[list] = []
for z in range(_N_ZONES):
if raw[z] is not None:
out.append(raw[z])
else:
nearest = min(populated, key=lambda p: abs(p - z))
out.append(list(raw[nearest]))
return out
def analyze(frames: list[np.ndarray]) -> GradeStats:
"""Distill grade statistics from a list of float32 RGB frames in [0,1]."""
if not frames:
raise ValueError("analyze() needs at least one frame")
labs = [_to_lab(f) for f in frames]
stacked = np.concatenate([l.reshape(-1, 3) for l in labs], axis=0)
L, a, b = stacked[:, 0], stacked[:, 1], stacked[:, 2]
chroma = np.sqrt(a.astype(np.float64) ** 2 + b.astype(np.float64) ** 2)
return GradeStats(
zones=_zone_stats(L, a, b),
lab_mean=[float(L.mean()), float(a.mean()), float(b.mean())],
lab_std=[float(L.std()), float(a.std()), float(b.std())],
l_cdf=[float(v) for v in _cdf_of_l(L)],
black_point=float(np.percentile(L, 1)),
white_point=float(np.percentile(L, 99)),
contrast=float(L.std()),
saturation=float(chroma.mean()),
warmth=float(b.mean()),
tint=float(a.mean()),View on GitHub (pinned to 8321021c54)