affaan-m/ECC · error · ContractError
CV effect has an invalid subject anchor
Error message
CV effect {event.get('effect')} has an invalid subject anchor What it means
ContractError (f-string) raised when the subject anchor dict is structurally complete but its 'mode' value is not one of the allowed tracking modes: object_track, point_track, or segmentation_track. The contract restricts anchors to these three track types.
Solutions
- Set mode to exactly one of: object_track, point_track, segmentation_track.
- Map your tracker's output type to the closest contract mode before validating.
- Add an enum check in your generator against the same set the contract uses.
- Catch ContractError and print the invalid mode value to speed up authoring fixes.
Example fix
// before
anchor = {..., "mode": "bounding_box", ...}
// after
anchor = {..., "mode": "object_track", ...} Defensive patterns
Strategy: validation
Validate before calling
VALID_MODES = {"object_track", "point_track", "segmentation_track"}
if anchor.get("mode") not in VALID_MODES:
raise ValueError(f"anchor mode must be one of {sorted(VALID_MODES)}") Type guard
def has_valid_track_mode(anchor) -> bool:
return isinstance(anchor, dict) and anchor.get("mode") in {"object_track", "point_track", "segmentation_track"} Try / catch
try:
validate_effect_recipe(recipe, reference_durations)
except ContractError as exc:
if "invalid subject anchor" in str(exc):
anchor["mode"] = normalize_track_mode(anchor["mode"])
else:
raise Prevention
- Define the three valid modes as an enum shared by generator and validator
- Map external tracker type names to contract modes at ingestion
- Add an enum membership test to your recipe CI
- Reject mode aliases (e.g. bbox, face) at authoring time
When it happens
Trigger: Calling validate_effect_recipe with an anchor whose mode is e.g. "bbox", "face", "object", "tracking", or a typo like "object_tracks". Any value outside the three-element set fails.
Common situations: Using mode names from a different tracking library's vocabulary; typos or pluralization mistakes; older recipe formats that used a different mode enum before the contract standardized the three values.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- anchor evidence source duration is not bound to its receipt…
- artifact has invalid modality binding
- assigneeKind must be 'agent' or 'human'.
- CV effect lacks a valid subject anchor
- CV effect must fail closed on anchor loss
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/ec6e7c85c22797e3.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:240
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")
expected_duration = reference_durations.get(digest) if isinstance(digest, str) else None
if expected_duration is None or anchor.get("source_duration") != expected_duration:
raise ContractError("anchor evidence source duration is not bound to its receipt reference")
for event in events:
placement = event.get("placement")
if not isinstance(placement, dict) or not {"safe_area", "max_coverage", "occlusion_policy"}.issubset(placement):
raise ContractError(f"effect {event.get('effect')} lacks placement constraints")
def validate_provenance(payload: dict[str, Any]) -> None:View on GitHub (pinned to 8321021c54)