{"record":{"id":"e87381c356ba06ae","repo":"affaan-m/ECC","slug":"receipt-output-already-exists-output","errorCode":null,"errorMessage":"Receipt output already exists: {output}","messagePattern":"Receipt output already exists: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/assets.py","lineNumber":187,"sourceCode":"    if request is None:\n        raise ValueError('Asset request_id/modality does not match the bundle')\n    result = dict(request_id=request_id, **{key: request[key] for key in _TASTE_FIELDS})\n    if verify:\n        if any(asset.get(key) != value for key, value in result.items()):\n            raise ValueError('Asset taste lineage differs from its bundle request')\n    elif any(key in asset for key in _TASTE_FIELDS):\n        raise ValueError('Taste fields are derived from the bundle, not supplied')\n    return result\n\n\ndef ingest_assets(config_path: str | Path, out_receipt: str | Path) -> dict[str, Any]:\n    \"\"\"Bind local assets/provenance/lineage; write a new receipt, never overwrite.\"\"\"\n    config_file = _path(config_path, Path.cwd())\n    config = _load(config_file)\n    base = config_file.parent\n    output = _path(out_receipt, Path.cwd())\n    if output.exists():\n        raise ValueError(f'Receipt output already exists: {output}')\n    binding, requests = (_bundle(config['bundle_dir'], base, False)\n                         if 'bundle_dir' in config else (None, {}))\n    records = []\n    for asset in _assets(config.get('assets')):\n        record = {key: asset[key] for key in ('id', 'modality', 'origin')}\n        record.update(_taste(asset, requests, False))\n        record.update(_fingerprint(_path(asset.get('path'), base), asset['modality']))\n        provenance = _provenance(asset, base, False)\n        if provenance is not None:\n            record['provider_provenance'] = provenance\n        records.append(record)\n    inputs = config.get('input_artifacts', [])\n    if not isinstance(inputs, list):\n        raise ValueError('input_artifacts must be a list of local paths')\n    receipt = dict(schema=SCHEMA, provider_calls=0, provider_execution=False,\n                   assets=records, input_artifacts=[_fingerprint(_path(p, base)) for p in inputs])\n    if binding is not None:\n        receipt['bundle_receipt'] = binding","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/assets.py#L169-L205","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nreceipt = ingest_assets('config.json', 'receipt.json')  # second run\n# after\nfrom datetime import datetime\nreceipt = ingest_assets('config.json', f\"receipt-{datetime.now().isoformat(timespec='seconds')}.json\")","handlingStrategy":"validation","validationCode":"from pathlib import Path\nout = Path('receipt.json')\nassert not out.exists(), 'pick a new receipt path'","typeGuard":null,"tryCatchPattern":"try:\n    ingest_assets(cfg, out_path)\nexcept ValueError as e:\n    if 'already exists' in str(e):\n        out_path = unique_receipt_name()  # e.g. timestamped\n        ingest_assets(cfg, out_path)\n    else:\n        raise","preventionTips":["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."],"tags":["filesystem","exclusive-write","idempotency","receipt"],"backgroundTag":"file-already-exists","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}