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
timeline.py raises ValueError('no clips to write - a timeline needs at least one event') in _normalise when the resulting normalized clip list is empty, i.e. the caller passed an empty clips list. A timeline with zero events cannot produce valid FCPXML/EDL.
Solutions
- Pass at least one valid clip dict with path and positive duration.
- Check why the clips list is empty — log/inspect it before calling.
- Guard at the call site: `if not clips: skip / raise earlier with context`.
- Fix the upstream collection/filtering that produced an empty list.
Example fix
// before
build_fcpxml([]) # ValueError
// after
if not clips:
raise ValueError('no clips selected; nothing to build')
build_fcpxml(clips, fps=30) Defensive patterns
Strategy: validation
Validate before calling
def require_non_empty(clips):
if not clips:
raise ValueError('no clips to write - a timeline needs at least one event')
return clips Type guard
def has_clips(clips) -> bool:
return isinstance(clips, list) and len(clips) > 0 Try / catch
try:
write_timeline(clips, out_path, fmt='fcpxml')
except ValueError as e:
if 'no clips to write' in str(e):
logger.warning('nothing to build; skipping timeline output')
return None Prevention
- Check clip selection results before attempting output
- Log the count of collected clips at each pipeline stage
- Fail fast when a filter step empties the clip list
- Treat an empty media directory as a pipeline error, not a silent skip
When it happens
Trigger: Calling build_fcpxml or build_edl (or write_timeline) with clips=[] or None-ish empty input.
Common situations: Upstream filter step removed all clips; file list was empty because the directory had no media; conditional logic skipped adding clips silently.
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/6411d7df6367f3bd.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/taste/timeline.py:235
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 emit 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:
"""Absolute ``file://`` URI. Works for paths that do not exist yet."""
p = Path(path)
if not p.is_absolute():
p = Path.cwd() / p
# as_uri() percent-escapes correctly; normalise away '..' without resolving
# symlinks or requiring the file to exist.
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}"View on GitHub (pinned to 8321021c54)