affaan-m/ECC · error · ValueError

Asset taste lineage differs from its bundle request

Error message

Asset taste lineage differs from its bundle request

What it means

In _taste with verify=True (validate_assets path), the asset's stored taste fields (request_id, genre_number, genre_slug, style_fingerprint, reference_sha256) are compared against the values recorded in the bundle request. Any difference — including a mutated request_id or tampered lineage in the receipt — raises this error. The receipt's lineage must be byte-identical to what the validated bundle records.

Solutions

  1. Re-run ingest_assets against the correct bundle to produce a fresh receipt instead of editing the old one.
  2. Diff the receipt asset fields against <bundle_dir>/manifests/<modality>.json requests to find the differing field.
  3. If the bundle changed since ingest, restore the original bundle (validated by its receipt fingerprint) or re-ingest with the new bundle.
  4. Do not mutate request_id on a receipt record; it must equal the bundle request's id.

Example fix

# before: hand-edited receipt asset
{"request_id": "req-001", "genre_slug": "cyberpunk-noir", ...}
# after: regenerate the receipt from the bundle
receipt = ingest_assets('ingest.config.json', 'receipt.new.json')
Defensive patterns

Strategy: validation

Validate before calling

def lineage_matches(asset, request):
    fields = ('request_id','genre_number','genre_slug','style_fingerprint','reference_sha256')
    return all(asset.get(k) == request.get(k) for k in fields)
# check each receipt asset against its bundle manifest request before validate_assets

Try / catch

try:
    validate_assets('receipt.json')
except ValueError as e:
    if 'taste lineage differs' in str(e):
        reingest_fresh_receipt()
    else:
        raise

Prevention

When it happens

Trigger: Calling validate_assets on a receipt whose asset record's request_id or any _TASTE_FIELDS value differs from the corresponding bundle manifest request; hand-editing a receipt's genre fields; re-validating a receipt against a different (newer) bundle than the one used at ingest time.

Common situations: Manual receipt edits (fixing fields by hand); receipts copied across projects and re-validated against a different bundle; bundle regenerated so request contents changed while the old receipt was kept; accidental asset-record mutation during post-processing scripts.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/39354cc498b4ccc1. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/assets.py:174

            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)
                         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')}

View on GitHub (pinned to 8321021c54)