affaan-m/ECC · error · FalError
merge_videos() needs at least one video URL
Error message
merge_videos() needs at least one video URL
What it means
merge_videos in the taste falapi client composites a list of already-generated video URLs via the fal merge endpoint; an empty video_urls list leaves nothing to merge and is rejected before submitting.
Solutions
- Ensure at least one generated clip URL exists before calling merge_videos
- Fix upstream video generation steps that returned no URLs
- Fail fast in the caller: check len(video_urls) > 0 and raise a descriptive error
- If clips are conditionally produced, skip the merge step when only zero-or-one clip exists
Example fix
// before
clips = [g for g in generate_all() if g.ok]
falapi.merge_videos([c.url for c in clips]) # FalError when all failed
// after
clip_urls = [c.url for c in clips]
if not clip_urls:
raise RuntimeError("merge_videos skipped: no clips were generated")
merged = falapi.merge_videos(clip_urls) Defensive patterns
Strategy: validation
Validate before calling
if not video_urls:
raise ValueError("merge_videos skipped: no video URLs available") Type guard
def can_merge(video_urls) -> bool:
return isinstance(video_urls, list) and len(video_urls) > 0 Try / catch
try:
merged = falapi.merge_videos(urls)
except falapi.FalError as e:
if "at least one video" in str(e):
print("No clips produced upstream; skipping merge") Prevention
- Count successfully generated clips before the merge stage
- Fail loudly when generation stages yield zero outputs instead of passing empty lists
- Skip merge entirely when fewer than 2 clips exist (nothing to concatenate)
- Collect and report per-stage failures so empty lists are diagnosable
When it happens
Trigger: merge_videos([]) — typically because upstream video-generation steps produced no URLs (failures collected into an empty list).
Common situations: Caller gathers generated clip URLs but all generation steps failed or were filtered out; forgot to pass the list; passing an empty list after filtering broken URLs.
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
- image_to_3d needs at least one image
- views must include 'input_image_url' (the front view)
- application bundle differs from its bound evidence
- At least one video is required
- cannot upload, file does not exist
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/dc39be10c51a4d80.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-distillation/scripts/taste/falapi.py:647
result = submit(ENDPOINTS["extract_frame"], payload, timeout)
return first_url(result, ENDPOINTS["extract_frame"])
def compose(tracks: list[dict], *, timeout: int = 900) -> str:
"""Composite timeline tracks into one video. Returns the output URL.
``tracks`` is passed straight through so the caller owns the timeline
shape; the ffmpeg-api track schema is another default worth verifying
before a live run.
"""
result = submit(ENDPOINTS["compose"], {"tracks": tracks}, timeout)
return first_url(result, ENDPOINTS["compose"])
def merge_videos(video_urls: list[str], *, timeout: int = 900) -> str:
"""Concatenate videos end to end. Returns the merged URL."""
if not video_urls:
raise FalError("merge_videos() needs at least one video URL")
payload = {"video_urls": list(video_urls)}
result = submit(ENDPOINTS["merge_videos"], payload, timeout)
return first_url(result, ENDPOINTS["merge_videos"])
# ---------------------------------------------------------------------------
# download
# ---------------------------------------------------------------------------
MAX_DOWNLOAD_BYTES = 2 * 1024 * 1024 * 1024 # bounded large video/GLB downloads
def _validate_download_url(url: str) -> None:
try:
parsed = urllib.parse.urlsplit(url)
host = parsed.hostname or ""
valid = (parsed.scheme == "https" and not parsed.usernameView on GitHub (pinned to 8321021c54)