affaan-m/ECC · error · ValueError

nothing to concatenate

Error message

nothing to concatenate

What it means

concat() joins a list of clip files into one video via an ffmpeg concat demuxer invocation. It raises ValueError('nothing to concatenate') when the clips list is empty, because writing an empty concat listing and invoking ffmpeg would produce a meaningless/failed run.

Solutions

  1. Guard at the call site: only call concat when the clips list is non-empty, and decide what an empty result should mean for your pipeline.
  2. Trace why the upstream clip list is empty — check cut_take output directory and shot detection results.
  3. Log the number of clips before concat so empty lists surface earlier with context.
  4. If clips are generated by globbing, verify the glob pattern and directory actually match produced files.
  5. Fix any filter predicate that removed all clips unintentionally.

Example fix

// before
assemble.concat(clips, dst)  # ValueError if clips == []

// after
if not clips:
    raise SystemExit("no takes were cut; nothing to concatenate")
assemble.concat(clips, dst)
Defensive patterns

Strategy: validation

Validate before calling

if not clips:
    raise SystemExit("no clips produced upstream; skipping concat")

Type guard

def has_clips(clips: list) -> bool:
    return len(clips) > 0 and all(Path(c).exists() for c in clips)

Try / catch

try:
    assemble.concat(clips, dst)
except ValueError as exc:
    if str(exc) == "nothing to concatenate":
        log.warning("concat skipped: no clips")
        return None

Prevention

When it happens

Trigger: concat([]) called directly, or an upstream step (e.g. cut_take producing zero takes, filtered shot lists) yields an empty clips list that is passed through to concat.

Common situations: Shot detection found no shots so cut_take exported no clips; caller filtered all clips out by a predicate; path glob matched nothing; wiring bug passing the wrong (empty) list variable.

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/245f4da20fd4f116. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-distillation/scripts/taste/assemble.py:181

        f"[0:v]format=gbrp[base];"
        f"[base][ov]blend=all_mode={blend or 'screen'}:shortest=1,format=yuv420p"
    )
    _run([
        "ffmpeg", "-nostdin", "-loglevel", "error", "-y",
        # Keep the still alive until the video ends; shortest=1 otherwise
        # terminates every shot after the image's single decoded frame.
        "-i", str(clip), "-loop", "1", "-i", str(image), "-filter_complex", fc,
        "-c:v", "libx264", "-crf", "14", "-preset", "veryfast",
        "-pix_fmt", "yuv420p", "-an", str(dst),
    ])
    return Path(dst)


def concat(clips: list[str | Path], dst: str | Path, fps: float = 24.0) -> Path:
    """Join clips into one file. Assumes they already share codec and size."""
    clips = [Path(c) for c in clips]
    if not clips:
        raise ValueError("nothing to concatenate")
    dst = Path(dst)
    dst.parent.mkdir(parents=True, exist_ok=True)
    listing = dst.parent / f"{dst.stem}_concat.txt"
    listing.write_text("".join(f"file '{c.resolve().as_posix()}'\n" for c in clips))
    _run([
        "ffmpeg", "-nostdin", "-loglevel", "error", "-y",
        "-f", "concat", "-safe", "0", "-i", str(listing),
        "-vf", f"fps={fps:.6f}",
        "-c:v", "libx264", "-crf", "16", "-pix_fmt", "yuv420p", str(dst),
    ])
    listing.unlink(missing_ok=True)
    return dst


def normalize(
    src: str | Path,
    dst: str | Path,
    width: int,

View on GitHub (pinned to 8321021c54)