affaan-m/ECC · error · ContractError
CV effect must require a subject anchor
Error message
CV effect {event.get('effect')} must require a subject anchor What it means
ContractError (f-string) raised when an event whose effect name starts with 'cv_' (a computer-vision effect) does not have requires_subject_anchor set to exactly True. CV effects modify content relative to a tracked subject, so the contract mandates an explicit subject-anchor requirement on the event.
Solutions
- Set requires_subject_anchor: true on every cv_* event.
- Rename the effect to a non-cv_ prefix if it genuinely does not track a subject.
- Add an assertion in your recipe generator that cv_* events always include the flag.
- Catch ContractError and surface the specific event effect name from the message for authoring fixes.
Example fix
// before
{"time": 1.2, "effect": "cv_pixelate"}
// after
{"time": 1.2, "effect": "cv_pixelate", "requires_subject_anchor": true} Defensive patterns
Strategy: validation
Validate before calling
for event in recipe["events"]:
if str(event.get("effect", "")).startswith("cv_") and event.get("requires_subject_anchor") is not True:
raise ValueError(f"{event['effect']} must set requires_subject_anchor=true") Type guard
def cv_events_anchored(events) -> bool:
return all(
e.get("requires_subject_anchor") is True
for e in events
if str(e.get("effect", "")).startswith("cv_")
) Try / catch
try:
validate_effect_recipe(recipe, reference_durations)
except ContractError as exc:
if "must require a subject anchor" in str(exc):
for e in recipe["events"]:
if str(e.get("effect", "")).startswith("cv_"):
e["requires_subject_anchor"] = True
else:
raise Prevention
- Enforce the cv_ -> anchor requirement in your recipe generator
- Use a lint rule that flags cv_* events without requires_subject_anchor
- Set the flag as a boolean literal true, not 1 or "true"
- Keep effect naming and anchor policy in one schema definition
When it happens
Trigger: Calling validate_effect_recipe with an event like {"effect": "cv_blur", ...} missing requires_subject_anchor, or with requires_subject_anchor set to false, a truthy string, or 1 (anything not identically True).
Common situations: Renaming a generic effect to a cv_ prefix without updating anchor requirements; copying a non-CV event template; schema drift where requires_subject_anchor was made optional upstream.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- anchor evidence source duration is not bound to its receipt…
- CV effect has an invalid subject anchor
- CV effect lacks a valid subject anchor
- CV effect must fail closed on anchor loss
- effect lacks placement constraints
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/eb920822ab10a191.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:230
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")
intervals = [round(b - a, 6) for a, b in zip(times, times[1:])] # noqa: RUF007
if len(set(intervals)) <= 1:
raise ContractError("stochastic schedule is periodic; intervals must vary")
for period in range(1, len(intervals) // 2 + 1):
if all(intervals[index] == intervals[index % period] for index in range(len(intervals))):
raise ContractError("stochastic schedule is periodic; repeating interval cycle")
if recipe.get("periodic") is not False:
raise ContractError("effect recipe must explicitly declare periodic=false")
for event in events:
cv_effect = str(event.get("effect", "")).startswith("cv_")
if cv_effect and event.get("requires_subject_anchor") is not True:
raise ContractError(f"CV effect {event.get('effect')} must require a subject anchor")
if event.get("requires_subject_anchor"):
anchor = event.get("subject_anchor")
required = {
"mode", "target", "source_ref_sha256", "evidence_time",
"source_duration", "lost_policy",
}
if not isinstance(anchor, dict) or not required.issubset(anchor):
raise ContractError(f"CV effect {event.get('effect')} lacks a valid subject anchor")
if anchor.get("mode") not in {"object_track", "point_track", "segmentation_track"}:
raise ContractError(f"CV effect {event.get('effect')} has an invalid subject anchor")
if anchor.get("lost_policy") != "disable_effect_until_track_recovers":
raise ContractError(f"CV effect {event.get('effect')} must fail closed on anchor loss")
_validate_media_time(
anchor.get("evidence_time"), anchor.get("source_duration"),
label="anchor evidence time",
)
if reference_durations is not None:
digest = anchor.get("source_ref_sha256")View on GitHub (pinned to 8321021c54)