affaan-m/ECC · error · ValueError
Invalid asset origin
Error message
Invalid asset origin
What it means
Each asset must declare its origin from a fixed allowed set (ORIGINS). The library throws this when `asset.get('origin')` is absent or not in that tuple, because origin controls provenance rules (internal vs external_result) and provenance validation depends on it.
Solutions
- Set 'origin' to a value in the ORIGINS tuple (check the ORIGINS constant in assets.py for the exact allowed strings)
- Check the current ORIGINS definition if migrating from an older manifest — origin vocabulary may have changed
- Inspect the offending asset entry to confirm the origin field exists and its exact value
Example fix
// before
{"id": "a1", "modality": "image", "origin": "generated"}
// after
{"id": "a1", "modality": "image", "origin": "internal"} Defensive patterns
Strategy: validation
Validate before calling
ORIGINS = frozenset(load_origins_from_library())
for a in assets:
if a.get("origin") not in ORIGINS:
raise ValueError(f"asset {a.get('id')}: invalid origin {a.get('origin')!r}") Type guard
def has_valid_origin(a: dict) -> bool:
return a.get("origin") in KNOWN_ORIGINS Try / catch
try:
ingest_assets(assets)
except ValueError as e:
if str(e) == "Invalid asset origin":
log.error("check 'origin' values against ORIGINS in assets.py"); revalidate_after_fix()
else:
raise Prevention
- Import ORIGINS from the library instead of hardcoding origin strings
- Keep manifests generated by tooling, not hand-edited
- Add enum validation to your manifest CI checks
When it happens
Trigger: ingest_assets or validate_assets called with an asset whose 'origin' key is missing, misspelled (e.g. 'external result', 'ExternalResult'), or uses a legacy origin name no longer in ORIGINS.
Common situations: Hand-edited asset manifests; manifests produced by an older tool version with different origin vocabulary; forgetting origin entirely when writing assets by hand; copying assets between projects with different origin schemes.
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
- modality must be image, video or 3d_asset
- Provider provenance requires external_result origin
- -32602
- a claim token is required
- a confirmed nonempty coordinate is required
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/50bd2290ce7de25c.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/assets.py:102
raise ValueError('Expected a JSON object')
return data
def _assets(value: Any) -> list[dict[str, Any]]:
if not isinstance(value, list) or not value:
raise ValueError('assets must be a nonempty list')
ids = set()
for asset in value:
if not isinstance(asset, dict):
raise ValueError('Each asset must be an object')
asset_id = _text(asset.get('id'), 'asset id')
if asset_id in ids:
raise ValueError(f'Duplicate asset id: {asset_id}')
ids.add(asset_id)
if asset.get('modality') not in tuple(MODALITIES):
raise ValueError('modality must be image, video or 3d_asset')
if asset.get('origin') not in tuple(ORIGINS):
raise ValueError('Invalid asset origin')
return value
def _provenance(asset: dict[str, Any], base: Path, verify: bool) -> dict[str, Any] | None:
source = asset.get('provider_provenance')
if asset['origin'] != 'external_result':
if source is not None:
raise ValueError('Provider provenance requires external_result origin')
return None
if not isinstance(source, dict):
raise ValueError('external_result requires provider provenance and local evidence')
provider = _text(source.get('provider'), 'provider')
identifiers = {key: _text(source[key], key) for key in ('request_id', 'workflow_id')
if key in source}
if not identifiers:
raise ValueError('Provider provenance requires request_id or workflow_id')
if verify:
evidence = _verify_binding(source.get('evidence'), base)View on GitHub (pinned to 8321021c54)