affaan-m/ECC · error · ValueError
no clips to write - a timeline needs at least one event
Error message
no clips to write - a timeline needs at least one event
What it means
normalise_clips() builds the normalized clip list for timeline export; if the input timeline produced zero events it raises ValueError because FCPXML/EDL writers cannot represent an empty timeline. The library refuses to emit a structurally empty sequence rather than writing a broken file.
Solutions
- Verify the timeline object passed to build_fcpxml/build_edl contains at least one event before calling
- Check that input parsing (e.g. parse_edl of the source) actually yielded clips; log its length
- If empty timelines are legitimate in your workflow, check clip count first and skip export or emit a placeholder
Example fix
// before
xml = build_fcpxml(timeline)
// after
if not timeline.events:
print("timeline is empty; nothing to export")
else:
xml = build_fcpxml(timeline) Defensive patterns
Strategy: validation
Validate before calling
if not timeline_events:
raise SystemExit("timeline has no events; nothing to export") Type guard
def has_clips(clips) -> bool:
return isinstance(clips, (list, tuple)) and len(clips) > 0 Try / catch
try:
xml = build_fcpxml(timeline)
except ValueError as e:
if "no clips to write" in str(e):
print("skipping export: empty timeline")
else:
raise Prevention
- Check len(timeline.events) before every export call
- Log the source parse result length to confirm clips were ingested
- Filter zero-length clips upstream and report when filtering empties the timeline
When it happens
Trigger: Calling build_fcpxml or build_edl with a timeline whose event list is empty, or where every event was filtered out during normalization (e.g. zero-length clips dropped before the `if not out` check).
Common situations: Scripts importing an empty EDL/JSON source, timelines where all clips were trimmed to zero duration, or a typo passing the wrong variable (an empty list) as the events argument.
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
- no clips to write - a timeline needs at least one event
- at least one explicit seed is required
- At least one guided harness must be selected
- at least one non-empty
- at least one placement is required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/1c41f2a5d62711bb.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/export.py:71
if not path:
raise ValueError(f"clip {i} has no 'path'")
dur = float(c.get("duration") or 0.0)
if dur <= 0:
raise ValueError(f"clip {i} ({path}) has non-positive duration {dur!r}")
frames = max(1, seconds_to_frames(dur, fps)) # never a zero-length event
name = str(c.get("name") or Path(path).stem)
out.append(
{
"path": path,
"name": name,
"frames": frames,
"offset_frames": offset,
"seconds": dur,
}
)
offset += frames
if not out:
raise ValueError("no clips to write - a timeline needs at least one event")
return out
def _file_uri(path: str) -> str:
p = Path(path)
if not p.is_absolute():
p = Path.cwd() / p
return Path(str(p)).absolute().as_uri()
def _format_name(width: int, height: int, fps: float | Fraction) -> str:
f = fps_fraction(fps)
rate = float(f)
label = f"{rate:.2f}".rstrip("0").rstrip(".").replace(".", "")
return f"FFVideoFormat{height}p{label}"
def _is_drop_frame(fps: float | Fraction) -> bool:View on GitHub (pinned to 8321021c54)