affaan-m/ECC · error · ValueError
clip ( ) has non-positive duration
Error message
clip {i} ({path}) has non-positive duration {dur!r} What it means
timeline.py raises ValueError('clip {i} ({path}) has non-positive duration {dur!r}') in _normalise when a clip's duration is 0 or negative. Durations must be positive so each event occupies at least one frame in the output timeline.
Solutions
- Provide a positive 'duration' in seconds for each clip.
- Probe actual media durations (ffprobe) instead of hardcoding 0.
- Guard before building: `assert all(c.get('duration', 0) > 0 for c in clips)`.
- Fix unit conversion so durations are seconds, not frames or milliseconds misread.
Example fix
// before
{"path": "a.mp4", "duration": 0}
// after
{"path": "a.mp4", "duration": 5.0} Defensive patterns
Strategy: validation
Validate before calling
def validate_clip_durations(clips):
for i, c in enumerate(clips):
try:
dur = float(c.get('duration') or 0.0)
except (TypeError, ValueError):
raise ValueError(f'clip {i} duration not numeric')
if dur <= 0:
raise ValueError(f'clip {i} non-positive duration {dur!r}')
return True Type guard
def has_positive_duration(c) -> bool:
try:
return float(c.get('duration') or 0.0) > 0
except (TypeError, ValueError):
return False Try / catch
try:
edl = build_edl(clips, fps=30)
except ValueError as e:
if 'non-positive duration' in str(e):
logger.error('bad duration in clips: %s', e)
raise Prevention
- Probe real media durations with ffprobe instead of hardcoding
- Keep durations in seconds consistently (document units)
- Require 'duration' explicitly rather than relying on the 0.0 default
- Validate clip lists in a preprocessing pass before timeline building
When it happens
Trigger: Calling build_fcpxml/build_edl with a clip whose 'duration' is 0, missing (defaults to 0.0), negative, or a non-numeric string that float() coerces oddly.
Common situations: Duration computed from a failed metadata probe returning 0; placeholder clips with duration 0; unit mistakes (frames given where seconds expected producing 0 after rounding); missing 'duration' key entirely.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- clip ( ) has non-positive duration
- base_track_count exceeds target video tracks
- clip has no 'path
- clip has no 'path
- clip ( ) has non-positive duration
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/f6c0370c5bcafc4f.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/taste/timeline.py:221
# ---------------------------------------------------------------------------
def _normalise(clips: Iterable[dict], fps: float | Fraction) -> list[dict]:
"""Validate clips and pre-compute integer frame counts and offsets.
Returns dicts with ``path``, ``name``, ``frames`` (int, >= 1) and
``offset_frames`` (int). Working in frames from here down is what makes the
sequence duration exactly the sum of the clip durations.
"""
out: list[dict] = []
offset = 0
for i, c in enumerate(clips):
path = str(c.get("path") or "")
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:View on GitHub (pinned to 8321021c54)