{"record":{"id":"35dac4cbea8ec98d","repo":"affaan-m/ECC","slug":"local-only-preservation-cannot-contain-candidates-or-inserts","errorCode":null,"errorMessage":"local-only preservation cannot contain candidates or inserts","messagePattern":"local-only preservation cannot contain candidates or inserts","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/integration.py","lineNumber":360,"sourceCode":"    _object(config, _REQUIRED, _OPTIONAL)\n    if len(_canonical(config)) > _MAX_JSON:\n        raise ValueError(\"application config exceeds local size limit\")\n    if local_only:\n        if compiled_input is not None:\n            raise ValueError(\"local-only preservation cannot accept provider input\")\n    else:\n        _object(compiled_input, {\"source_video\", \"compiled_prompt\"})\n        url = urlsplit(_text(compiled_input[\"source_video\"]))\n        if url.scheme != \"https\" or not url.hostname or url.username or url.password:\n            raise ValueError(\"source reference must be HTTPS without embedded credentials\")\n        _text(compiled_input[\"compiled_prompt\"])\n    cfg = copy.deepcopy(config)\n    for key in (\"audio\", \"candidates\", \"inserts\", \"historical_receipts\"):\n        cfg.setdefault(key, [])\n        if not isinstance(cfg[key], list):\n            raise ValueError(\"bundle collections must be lists\")\n    if local_only and (cfg[\"candidates\"] or cfg[\"inserts\"]):\n        raise ValueError(\"local-only preservation cannot contain candidates or inserts\")\n    tracks = _snapshot(cfg[\"baseline\"])\n    _binding(cfg[\"source\"], tracks, cfg[\"baseline\"])\n    audio_keys = [_binding(item, tracks, cfg[\"baseline\"], audio=True) for item in cfg[\"audio\"]]\n    expected_audio = {(t, i) for t, clips in tracks.items() if t.startswith(\"audio\")\n                      for i in range(len(clips))}\n    if len(set(audio_keys)) != len(audio_keys) or set(audio_keys) != expected_audio:\n        raise ValueError(\"every original audio clip must be preserved exactly once\")\n    stack = _preserved_stack(cfg[\"protected_intervals\"], tracks, cfg[\"baseline\"][\"timeline_range\"])\n    input_hash = None if local_only else _digest(compiled_input)\n    edit_hash = _digest({key: cfg[key] for key in _REQUIRED})\n    if not local_only:\n        candidates = _candidates(cfg[\"candidates\"], cfg[\"source\"][\"media\"][\"sha256\"],\n                                 input_hash, compiled_input[\"source_video\"])\n        _inserts(cfg[\"inserts\"], candidates, cfg, input_hash, edit_hash)\n    for receipt in cfg[\"historical_receipts\"]:\n        _artifact(receipt)\n    result = {**cfg, \"schema_version\": 1, \"mode\": \"preserve_native_timeline\",\n              \"provider_calls\": 0, \"provider_execution\": False, \"dry_run\": True, \"submit\": False,","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/integration.py#L342-L378","documentation":"Local-only mode is strictly a preservation bundle: it must contain zero candidates and zero inserts. If either collection is non-empty while local_only is True, the bundle would silently mix provider-derived edits into a 'preservation' artifact, so it is rejected.","triggerScenarios":"build_application_bundle(cfg, None, local_only=True) where cfg['candidates'] or cfg['inserts'] is a non-empty list (e.g. leftover insert entries from a previous hosted run).","commonSituations":"Re-running a previous hosted bundle build with local_only flipped on without clearing proposals; a generic template that always emits empty-ish but non-empty default candidate arrays.","solutions":["Set cfg['candidates'] = [] and cfg['inserts'] = [] before local-only bundling","Build the bundle with local_only=False if you actually want the candidates/inserts applied","Split the config: preservation-only config for local_only, full config for hosted mode"],"exampleFix":"// before\nbuild_application_bundle({**cfg, \"inserts\": [ins]}, None, local_only=True)\n// after\nbuild_application_bundle({**cfg, \"inserts\": [], \"candidates\": []}, None, local_only=True)","handlingStrategy":"validation","validationCode":"if local_only and (cfg.get(\"candidates\") or cfg.get(\"inserts\")):\n    raise ValueError(\"local-only mode requires empty candidates and inserts\")","typeGuard":"def is_preservation_only(cfg):\n    return not cfg.get(\"candidates\") and not cfg.get(\"inserts\")","tryCatchPattern":"try:\n    bundle = build_application_bundle(cfg, None, local_only=True)\nexcept ValueError as e:\n    if \"cannot contain candidates or inserts\" in str(e):\n        cfg = {**cfg, \"candidates\": [], \"inserts\": []}\n        bundle = build_application_bundle(cfg, None, local_only=True)\n    else:\n        raise","preventionTips":["Keep separate config templates for preservation vs edit bundles","Clear proposals before switching to local-only mode","Assert empty proposal collections in local-mode CI checks","Document the invariant in your bundle-authoring guide"],"tags":["validation","mutually-exclusive","local-mode"],"backgroundTag":"mutually-exclusive-options","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"}