affaan-m/ECC · error · ContractError
effect event start and duration must be finite positive…
Error message
effect event start and duration must be finite positive timeline values
What it means
Each event in the schedule must have a 'time' (>= 0) and a 'duration' (> 0) that are both finite real numbers. Missing keys, strings, bools, NaN/inf, negative starts, or zero/negative durations all raise this error.
Solutions
- Ensure every event has numeric time >= 0 and duration > 0 (floats or ints).
- Convert string/None values to floats before validation and reject non-numeric ones.
- Clamp or reject negative starts and zero durations at recipe-generation time.
Example fix
# before
event = {"time": "0.5", "duration": 0}
# after
event = {"time": 0.5, "duration": 2.0} Defensive patterns
Strategy: validation
Validate before calling
for ev in recipe["events"]:
t, d = ev.get("time"), ev.get("duration")
ok = (isinstance(t, (int, float)) and not isinstance(t, bool) and math.isfinite(t) and t >= 0
and isinstance(d, (int, float)) and not isinstance(d, bool) and math.isfinite(d) and d > 0)
if not ok:
raise ValueError(f"event has invalid time/duration: {t!r}, {d!r}") Type guard
def event_time_valid(ev: dict) -> bool:
t, d = ev.get("time"), ev.get("duration")
return (isinstance(t, (int, float)) and not isinstance(t, bool)
and math.isfinite(t) and t >= 0
and isinstance(d, (int, float)) and not isinstance(d, bool)
and math.isfinite(d) and d > 0) Try / catch
try:
validate_effect_recipe(recipe)
except ContractError as exc:
if "finite positive timeline values" in str(exc):
recipe = {**recipe, "events": [normalize_event_times(ev) for ev in recipe["events"]]}
validate_effect_recipe(recipe)
else:
raise Prevention
- Coerce event time/duration to float at config load, rejecting non-numeric strings.
- Default durations to a positive constant, never 0.
- Reject negative starts at generation time.
When it happens
Trigger: validate_effect_recipe called where any event dict lacks 'time' or 'duration', stores them as strings (e.g. from JSON/config), uses NaN/inf, has time < 0, or duration <= 0.
Common situations: Durations parsed from YAML/JSON kept as strings like '2.5'; a default duration of 0; negative start times from clip-relative offsets; None filling missing optional fields.
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
- effect event end exceeds the declared timeline
- effect lacks reference evidence
- effect recipe needs at least three scheduled events
- -32602
- a claim token is required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/cbcb71e1bf91d028.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:200
if not isinstance(recipe.get("seed"), int) or isinstance(recipe.get("seed"), bool):
raise ContractError("effect recipe must have an integer seed")
if recipe.get("rng_algorithm") != "python.random.Random/v1":
raise ContractError("effect recipe must declare its seeded RNG algorithm")
events = recipe.get("events")
if not isinstance(events, list) or len(events) < 3:
raise ContractError("effect recipe needs at least three scheduled events")
timeline = recipe.get("timeline_duration")
if not _is_finite_real(timeline):
raise ContractError("effect recipe must declare a finite positive timeline duration")
timeline = cast(float, timeline)
if float(timeline) <= 0:
raise ContractError("effect recipe must declare a finite positive timeline duration")
for event in events:
start = event.get("time")
duration = event.get("duration")
if (not _is_finite_real(start) or not _is_finite_real(duration)
or float(start) < 0 or float(duration) <= 0):
raise ContractError("effect event start and duration must be finite positive timeline values")
start = cast(float, start)
duration = cast(float, duration)
if float(start) + float(duration) > float(timeline) + 1e-9:
raise ContractError("effect event end exceeds the declared timeline")
evidence = event.get("evidence")
if not isinstance(evidence, dict):
raise ContractError(f"effect {event.get('effect')} lacks reference evidence")
_validate_media_time(
evidence.get("time"), evidence.get("source_duration"), label="effect evidence time"
)
if reference_durations is not None:
digest = evidence.get("reference_sha256")
expected_duration = reference_durations.get(digest) if isinstance(digest, str) else None
if expected_duration is None or evidence.get("source_duration") != expected_duration:
raise ContractError("effect evidence source duration is not bound to its receipt reference")
times = [float(event["time"]) for event in events]
if times != sorted(times) or len(times) != len(set(times)):
raise ContractError("effect event times must be unique and increasing")View on GitHub (pinned to 8321021c54)