affaan-m/ECC · error · ValueError

asset contains too few frames

Error message

asset contains too few frames: {asset}

What it means

tasteforge validates every placement's asset media metadata before allocating it onto the timeline. This error means the asset's probed frame count is lower than the number of frames the placement needs (start-to-end span), so appending it would produce a short or invalid clip.

Solutions

  1. Shorten the placement (reduce end so required frames <= asset frames)
  2. Replace the asset with a longer take or loop/extend the source media before importing
  3. Re-probe the asset to refresh cached metadata if frames changed on disk
  4. Verify the endpoint convention (inclusive/exclusive) is not inflating the frame count
  5. Check for fps mismatch causing the frame requirement to be computed at the wrong rate

Example fix

// before
{"asset": "sting.mov", "start": 0, "end": 500}  # asset has 240 frames
// after
{"asset": "sting.mov", "start": 0, "end": 240}
Defensive patterns

Strategy: validation

Validate before calling

info = probe(asset)
frames_needed = end - start
if info.get("frames", 0) < frames_needed:
    raise ValueError(f"asset {asset} has {info.get('frames')} frames, need {frames_needed}")

Type guard

def has_enough_frames(info: dict, needed: int) -> bool:
    return isinstance(info.get("frames"), int) and info["frames"] >= needed

Prevention

When it happens

Trigger: Calling allocate_placements (via apply_placements or plan) with a placement whose frames requirement, derived from record_frame/start and end, exceeds the probe-reported frame count of the asset (e.g. a 3-second clip placed into a 5-second span).

Common situations: Reusing a short sting/logo asset for a longer overlay; timeline rescaled to a slower fps increasing frame span; metadata cache holding stale frames values; off-by-one from inclusive vs exclusive end conventions inflating required frames.

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


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/fe0767261eb6800a. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/resolve.py:129

            raise ValueError("explicit opacity must be finite within 0..100")
        composite = _integer(event.get("composite"), "composite")
        raw_asset = event.get("asset")
        if not isinstance(raw_asset, (str, Path)) or not str(raw_asset):
            raise ValueError("asset must be a local regular file")
        asset = Path(raw_asset).expanduser().resolve()
        if not asset.is_file():
            raise ValueError(f"asset must be a local regular file: {asset}")
        alpha = event.get("requires_alpha", False)
        if not isinstance(alpha, bool):
            raise ValueError("requires_alpha must be boolean")
        key = str(asset)
        if key not in metadata:
            metadata[key] = probe(asset)
        info = metadata[key]
        if _fps(info.get("fps")) != rate:
            raise ValueError(f"asset fps differs from timeline: {asset}")
        if _integer(info.get("frames"), "asset frames", 1) < frames:
            raise ValueError(f"asset contains too few frames: {asset}")
        if alpha and info.get("has_alpha") is not True:
            raise ValueError(f"asset requires verified alpha: {asset}")
        checked.append(
            {
                "id": identifier,
                "asset": key,
                "record_frame": start,
                "frames": frames,
                "opacity": opacity,
                "composite": composite,
            }
        )
    if not checked:
        raise ValueError("at least one placement is required")
    ends, allocated = [], {}
    for event in sorted(checked, key=lambda entry: entry["record_frame"]):
        index = next(
            (i for i, end in enumerate(ends) if end <= event["record_frame"]), len(ends)

View on GitHub (pinned to 8321021c54)