affaan-m/ECC · error · ValueError
must be an integer >=
Error message
{label} must be an integer >= {minimum} What it means
resolve._integer validates that a numeric option is a real int (not a bool) and at least the given minimum, raising ValueError '<label> must be an integer >= <minimum>' otherwise. It backs allocate_placements and other placement resolution entry points.
Solutions
- Convert with a strict check: int(value) after verifying it is not a float with a fractional part, or round() a computed float
- Pass actual ints (e.g. frames=round(duration * fps)) into allocate_placements
- Fix upstream config parsing to coerce numeric fields to int before reaching resolve
Example fix
// before
allocate_placements(frames="12", ...) # string
// after
allocate_placements(frames=int("12"), ...) # or max(1, round(duration * fps)) Defensive patterns
Strategy: validation
Validate before calling
def is_count(v):
return isinstance(v, int) and not isinstance(v, bool) and v >= 0
assert is_count(frames), f"frames must be a non-negative int, got {frames!r}" Try / catch
try:
placements = allocate_placements(frames=frames, ...)
except ValueError as e:
frames = max(1, round(float(frames)))
placements = allocate_placements(frames=frames, ...) Prevention
- Coerce config numbers to int at the config-parsing boundary
- Never use bool as a count; guard with isinstance(v, bool) checks
- round() any computed float (duration * fps) before passing it
When it happens
Trigger: Passing frames=10.5 or frames="10" (non-int), frames=True (bool is explicitly rejected), or a value below the minimum such as frames=0 when minimum=1; passing None.
Common situations: Reading numeric options from JSON/YAML where they deserialize as floats or strings; using True/False as a count by mistake; computing a duration*fps in float and forgetting to round; CLI parsing that yields strings.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- base_track_count exceeds target video tracks
- Canonical session snapshot requires
- fps must be finite and positive
- fps must be positive, got
- Invalid : expected a JSON object
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/7699e559b68f5190.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/resolve.py:23
receipt; partial edits may remain and must be discarded/restored by the caller.
Composite values are explicit API integers, never guessed blend-mode names.
"""
from __future__ import annotations
import copy
import json
import math
import subprocess
from fractions import Fraction
from pathlib import Path
from .timeline import fps_fraction
def _integer(value, label, minimum=0):
if isinstance(value, bool) or not isinstance(value, int) or value < minimum:
raise ValueError(f"{label} must be an integer >= {minimum}")
return value
def _fps(value):
if isinstance(value, bool):
raise ValueError("fps must be finite and positive")
try:
number = float(Fraction(str(value)))
if not math.isfinite(number) or number <= 0:
raise ValueError("fps must be finite and positive")
return fps_fraction(number)
except (TypeError, ZeroDivisionError, OverflowError) as exc:
raise ValueError("invalid fps") from exc
def probe_asset(path):
"""Count decoded video frames; never infer source length from duration."""
result = subprocess.run(View on GitHub (pinned to 8321021c54)