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

  1. Verify the timeline object passed to build_fcpxml/build_edl contains at least one event before calling
  2. Check that input parsing (e.g. parse_edl of the source) actually yielded clips; log its length
  3. 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

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


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)