affaan-m/ECC · error · ValueError
explicit opacity must be finite within 0..100
Error message
explicit opacity must be finite within 0..100
What it means
When a placement event includes an 'opacity' key, allocate_placements requires it to be a non-bool int/float that is finite (not NaN/inf) and within 0..100; otherwise it raises ValueError('explicit opacity must be finite within 0..100'). Strings like '50' are rejected — opacity must be numeric.
Solutions
- Supply opacity as a plain number between 0 and 100 (e.g. 50, 87.5), not a string or bool
- Validate/convert at the boundary: `o = float(raw); assert 0 <= o <= 100 and math.isfinite(o)`
- Fix upstream math that produced NaN/inf (division by zero, log of negative) before assigning opacity
- Omit the 'opacity' key entirely if you want the default rather than passing None
Example fix
// before
{"id": "logo", "opacity": "50"}
// after
{"id": "logo", "opacity": 50} Defensive patterns
Strategy: validation
Validate before calling
import math
def valid_opacity(v):
return (not isinstance(v, bool)
and isinstance(v, (int, float))
and math.isfinite(v)
and 0 <= v <= 100)
assert valid_opacity(50) Type guard
def is_opacity(v) -> bool:
return isinstance(v, (int, float)) and not isinstance(v, bool) and math.isfinite(v) and 0 <= v <= 100 Try / catch
try:
resolve.allocate_placements(fps, count, placements)
except ValueError as e:
if 'opacity' in str(e):
raise PlacementError(f'bad opacity value in placements') from e
raise Prevention
- Keep opacity numeric (0–100) in configs, not strings
- Clamp computed opacity: `min(100.0, max(0.0, value))` and check isfinite
- Omit the key instead of passing None for defaults
When it happens
Trigger: Passing opacity='50' (string), opacity=True/False, opacity=None, NaN or float('inf') (e.g. from a bad JSON config or a division by zero upstream), or opacity=150.
Common situations: Config where opacity was entered as a percentage string; JSON parser can't produce NaN but Python float('nan') from upstream math can; a script computing opacity by division that yielded inf/nan; leaving opacity as a boolean toggle.
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
- Canonical session snapshot must be an object
- Canonical session snapshot requires
- Canonical session snapshot requires
- Canonical session snapshot requires
- frame/count must be an exact integer in range
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/6fba0d3371ef7fc2.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/resolve.py:111
"""
rate = _fps(fps)
_integer(base_track_count, "base_track_count")
checked, seen, metadata = [], set(), {}
for event in placements:
identifier = event.get("id")
if not isinstance(identifier, str) or not identifier or identifier in seen:
raise ValueError("placement id must be unique and nonempty")
seen.add(identifier)
start = _integer(event.get("record_frame"), "record_frame")
frames = _integer(event.get("frames"), "frames", 1)
opacity = event.get("opacity")
if (
isinstance(opacity, bool)
or not isinstance(opacity, (int, float))
or not math.isfinite(opacity)
or not 0 <= opacity <= 100
):
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}")View on GitHub (pinned to 8321021c54)