affaan-m/ECC · error · ValueError
Taste fields are derived from the bundle, not supplied
Error message
Taste fields are derived from the bundle, not supplied
What it means
In _taste with verify=False (ingest_assets path), an asset config supplied one of the derived taste fields (genre_number, genre_slug, style_fingerprint, reference_sha256) even though a bundle is present. Taste fields are derived exclusively from the bundle request; supplying them in the config is rejected so the bundle remains the single source of lineage truth. Only request_id may be supplied in the config.
Solutions
- Remove genre_number, genre_slug, style_fingerprint and reference_sha256 from the asset entry in the ingest config; keep only request_id.
- If you want those values, note they will be recomputed by ingest_assets from the bundle manifest request.
- Fix any config generator to emit only id, modality, origin, path, request_id (and optional provider_provenance) for bundle-bound assets.
Example fix
# before
{"id": "a1", "modality": "image", "origin": "local_passthrough", "request_id": "req-001", "genre_slug": "baroque"}
# after
{"id": "a1", "modality": "image", "origin": "local_passthrough", "request_id": "req-001"} Defensive patterns
Strategy: validation
Validate before calling
TASTE_FIELDS = ('genre_number','genre_slug','style_fingerprint','reference_sha256')
assert not any(k in asset for k in TASTE_FIELDS), 'strip derived taste fields from config' Prevention
- Emit only id/modality/origin/path/request_id in ingest configs.
- When round-tripping receipts into configs, project only the allowed keys.
- Document that taste fields are read-only derived values.
When it happens
Trigger: Calling ingest_assets with an asset entry that includes any of genre_number/genre_slug/style_fingerprint/reference_sha256 while bundle_dir is configured; copying a validated receipt's asset record back into the ingest config (which contains the derived fields); a script merging bundle output into the config.
Common situations: Round-tripping a receipt back into a config by copy-paste; users 'filling in' what look like missing fields; auto-generated configs that dump full asset objects including derived lineage.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Asset request_id/modality does not match the bundle
- application config exceeds local size limit
- at least one genre spec is required
- bundle collections must be lists
- candidate configuration exceeds 1 MiB
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/ccfe0835498a215e.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/assets.py:176
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)
if 'bundle_dir' in config else (None, {}))
records = []
for asset in _assets(config.get('assets')):
record = {key: asset[key] for key in ('id', 'modality', 'origin')}
record.update(_taste(asset, requests, False))
record.update(_fingerprint(_path(asset.get('path'), base), asset['modality']))View on GitHub (pinned to 8321021c54)