affaan-m/ECC · error · ValueError
external_result requires provider provenance and local…
Error message
external_result requires provider provenance and local evidence
What it means
An asset with origin 'external_result' MUST carry a dict-shaped 'provider_provenance'. The library throws this when provider_provenance is missing or not a dict, because external-origin assets are untrusted without documented provider evidence.
Solutions
- Add a provider_provenance dict with at least a 'provider' string plus request_id or workflow_id
- If the value is a JSON string, parse it into an object before ingestion
- Change origin to an internal value if the asset was not actually produced externally (then remove the provenance requirement path)
Example fix
// before
{"id": "a1", "origin": "external_result", "modality": "image"}
// after
{"id": "a1", "origin": "external_result", "modality": "image",
"provider_provenance": {"provider": "acme", "request_id": "req-123", "evidence_path": "artifacts/a1.png"}} Defensive patterns
Strategy: validation
Validate before calling
for a in assets:
if a.get("origin") == "external_result" and not isinstance(a.get("provider_provenance"), dict):
raise ValueError(f"asset {a['id']}: external_result needs a provider_provenance object") Type guard
def has_provenance_dict(a: dict) -> bool:
p = a.get("provider_provenance")
return a.get("origin") != "external_result" or isinstance(p, dict) Try / catch
try:
ingest_assets(assets)
except ValueError as e:
if "external_result requires provider provenance" in str(e):
raise ManifestError("fill provider_provenance for all external_result assets") from e
raise Prevention
- Never set origin='external_result' by hand without also filling provenance
- Serialize provenance as an object, never a JSON string
- Validate manifests with a schema requiring provenance for external_result
When it happens
Trigger: An asset with origin set to 'external_result' but no 'provider_provenance' key, or provider_provenance set to a string/list/None instead of a dict, passed to ingest_assets or validate_assets.
Common situations: Manually adding external assets without filling in provenance; a tool emitting provenance as a JSON string rather than an object; truncating provenance during serialization.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- a generated candidate cannot claim original-source identity
- anchor evidence source duration is not bound to its receipt…
- artifact cites an unknown provenance source
- artifact has an unbound source duration
- artifact has invalid reference path
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/a665271f1bcec4b3.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/assets.py:113
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)
else:
evidence = _fingerprint(_path(source.get('evidence_path'), base))
return dict(provider=provider, **identifiers, evidence=evidence,
verification='supplied_local_evidence_only')
def _verify_binding(value: Any, base: Path, modality: str | None = None) -> dict[str, Any]:
if not isinstance(value, dict):
raise ValueError('Missing artifact binding')
actual = _fingerprint(_path(value.get('path'), base), modality)
if type(value.get('bytes')) is not int or any(value.get(k) != v for k, v in actual.items()):View on GitHub (pinned to 8321021c54)