affaan-m/ECC · error · ValueError
Receipt output already exists
Error message
Receipt output already exists: {output} What it means
ingest_assets enforces exclusive receipt creation: before doing any work it checks whether the target receipt file already exists and raises if so. Receipts are append-only artifacts of an ingestion run and are never overwritten, so a fresh output path is required for every run.
Solutions
- Delete or move the existing receipt, or (preferred) choose a new output path for the new run.
- Use unique names per run, e.g. include a timestamp or run id: receipt-2026-09-16T10-30.json.
- Check output.exists() before invoking ingest_assets in scripts.
- Run ingest from a consistent working directory or pass absolute output paths to avoid accidental collisions.
Example fix
# before
receipt = ingest_assets('config.json', 'receipt.json') # second run
# after
from datetime import datetime
receipt = ingest_assets('config.json', f"receipt-{datetime.now().isoformat(timespec='seconds')}.json") Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
out = Path('receipt.json')
assert not out.exists(), 'pick a new receipt path' Try / catch
try:
ingest_assets(cfg, out_path)
except ValueError as e:
if 'already exists' in str(e):
out_path = unique_receipt_name() # e.g. timestamped
ingest_assets(cfg, out_path)
else:
raise Prevention
- Name receipts with a timestamp or run id.
- Check target existence in scripts before invoking ingest.
- Use absolute output paths and a fixed working directory.
When it happens
Trigger: Calling ingest_assets(config_path, out_receipt) where out_receipt resolves to an existing file (from a previous run, a manual copy, or an unintended path resolution); running the same command twice without changing the output name.
Common situations: Re-running a pipeline step after a partial failure while reusing the same receipt name; scripts hardcoding 'receipt.json' as output; running ingest from a different working directory so the relative out_receipt path resolves onto an existing file.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Cannot create exclusive receipt
- capsule.exists
- output already exists; choose a new --out
- receipt source cannot be securely read
- receipt source is not a safe regular file
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/e87381c356ba06ae.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/assets.py:187
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']))
provenance = _provenance(asset, base, False)
if provenance is not None:
record['provider_provenance'] = provenance
records.append(record)
inputs = config.get('input_artifacts', [])
if not isinstance(inputs, list):
raise ValueError('input_artifacts must be a list of local paths')
receipt = dict(schema=SCHEMA, provider_calls=0, provider_execution=False,
assets=records, input_artifacts=[_fingerprint(_path(p, base)) for p in inputs])
if binding is not None:
receipt['bundle_receipt'] = bindingView on GitHub (pinned to 8321021c54)