affaan-m/ECC · error · ValueError
Asset request_id/modality does not match the bundle
Error message
Asset request_id/modality does not match the bundle
What it means
During _taste (called by ingest_assets and validate_assets), an asset declares a bundle request_id, but the (modality, request_id) pair is not found among the requests loaded from the validated taste bundle's manifests. The library refuses to attach taste lineage (genre_number, genre_slug, style_fingerprint, reference_sha256) to an asset whose request does not exist in the bundle for that modality. This prevents silently pairing an asset with taste fields that belong to a different request.
Solutions
- Print the bundle manifests and confirm the exact (modality, request_id) pair exists: for each modality in image/video/3d_asset, read <bundle_dir>/manifests/<modality>.json and check the requests[].request_id values.
- Fix the asset's request_id in the ingest config to match a request under the same modality.
- If the modality of the asset changed, move the request id lookup to the correct modality's manifest or regenerate the bundle request for that modality.
- If the bundle was regenerated, update all configs to the new request ids (or re-run the bundle generation step and rewire).
Example fix
# before (config)
{"assets": [{"id": "a1", "modality": "video", "origin": "local_passthrough", "request_id": "req-001"}]}
# after (request req-001 lives under image, asset is video; use the video request id)
{"assets": [{"id": "a1", "modality": "video", "origin": "local_passthrough", "request_id": "req-002"}]} Defensive patterns
Strategy: validation
Validate before calling
import json, pathlib
def request_in_bundle(bundle_dir, modality, request_id):
manifest = json.loads(pathlib.Path(bundle_dir, 'manifests', f'{modality}.json').read_text())
return any(r.get('request_id') == request_id for r in manifest['requests'])
# assert request_in_bundle(cfg['bundle_dir'], asset['modality'], asset['request_id']) Type guard
def has_bundle_request(asset, requests):
rid = asset.get('request_id')
return isinstance(rid, str) and (asset.get('modality'), rid) in requests Prevention
- Keep a manifest of (modality, request_id) pairs and validate configs against it before ingest.
- Regenerate configs whenever the bundle is regenerated.
- Avoid hand-typing request ids; copy them from the manifest or generate configs programmatically.
- Never change an asset's modality without re-checking its request id.
When it happens
Trigger: Calling ingest_assets with an asset whose request_id does not exist in bundle manifests, or whose modality key (image/video/3d_asset) differs from the modality the request was filed under; calling validate_assets on a receipt containing such a mismatched (request_id, modality) combination. Also triggered by a bundle with manifests regenerated/renamed request ids after the config was written.
Common situations: Copy-pasting request ids between configs; regenerating a taste bundle (new random request ids) without updating asset configs; changing an asset's modality field without updating the request id; typos in request_id strings; referencing a request that lives under a different modality manifest.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Taste fields are derived from the bundle, not supplied
- application config exceeds local size limit
- Asset taste lineage differs from its bundle request
- at least one genre spec is required
- bundle collections must be lists
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/c462a888ffd9fc96.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/assets.py:170
for request in manifest['requests']:
key = (modality, _text(request.get('request_id'), 'request_id'))
if key in requests:
raise ValueError('Ambiguous duplicate bundle request')
requests[key] = request
if binding != _fingerprint(root / 'receipt.json'):
raise ValueError('Bundle changed during validation')
return binding, requests
def _taste(asset: dict[str, Any], requests: dict[Any, Any], verify: bool) -> dict[str, Any]:
if not requests:
if any(key in asset for key in (*_TASTE_FIELDS, 'request_id')):
raise ValueError('Taste claims require a validated bundle')
return {}
request_id = _text(asset.get('request_id'), 'bundle request_id')
request = requests.get((asset['modality'], request_id))
if request is None:
raise ValueError('Asset request_id/modality does not match the bundle')
result = dict(request_id=request_id, **{key: request[key] for key in _TASTE_FIELDS})
if verify:
if any(asset.get(key) != value for key, value in result.items()):
raise ValueError('Asset taste lineage differs from its bundle request')
elif any(key in asset for key in _TASTE_FIELDS):
raise ValueError('Taste fields are derived from the bundle, not supplied')
return result
def ingest_assets(config_path: str | Path, out_receipt: str | Path) -> dict[str, Any]:
"""Bind local assets/provenance/lineage; write a new receipt, never overwrite."""
config_file = _path(config_path, Path.cwd())
config = _load(config_file)
base = config_file.parent
output = _path(out_receipt, Path.cwd())
if output.exists():
raise ValueError(f'Receipt output already exists: {output}')
binding, requests = (_bundle(config['bundle_dir'], base, False)View on GitHub (pinned to 8321021c54)