affaan-m/ECC · error · ValueError

local-only preservation cannot accept provider input

Error message

local-only preservation cannot accept provider input

What it means

When local_only is True, build_application_bundle enforces a pure local preservation mode: compiled_input (the provider-side compilation result) must be None. Passing any provider output while claiming local-only is a contradictory request, so it is rejected to keep hosted-source provenance out of local bundles.

Solutions

  1. Pass compiled_input=None when local_only=True: build_application_bundle(cfg, None, local_only=True)
  2. Remove the provider_input field from the bundle dict before validate_application_bundle in local-only mode
  3. If you actually need the compiled input, call with local_only=False so the HTTPS source checks run instead

Example fix

// before
build_application_bundle(cfg, compiled_input, local_only=True)
// after
build_application_bundle(cfg, None, local_only=True)
Defensive patterns

Strategy: validation

Validate before calling

if local_only and compiled_input is not None:
    raise ValueError("drop compiled_input in local-only mode")

Type guard

def is_valid_mode(ci, local_only):
    return (local_only and ci is None) or (not local_only and isinstance(ci, dict))

Try / catch

try:
    bundle = build_application_bundle(cfg, ci, local_only=local_only)
except ValueError as e:
    if "cannot accept provider input" in str(e):
        bundle = build_application_bundle(cfg, None, local_only=True)
    else:
        raise

Prevention

When it happens

Trigger: build_application_bundle(cfg, compiled_input=<dict>, local_only=True) — e.g. reusing a previous call site that still passes the compiled input while flipping local_only to True; validate_application_bundle on a bundle whose provider_input is non-null but local_only is true.

Common situations: Migrating a script from hosted to local-only mode and forgetting to drop the compiled_input argument; a bundle saved in hosted mode later validated with local_only forced on.

Related errors


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

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/integration.py:347

                    "compiled_input_sha256": input_hash,
                    "edit_context_sha256": edit_hash,
                    "candidate_range": source, "timeline_range": target}
        if not isinstance(evidence, dict) or any(
                _canonical(evidence.get(key)) != _canonical(value) for key, value in expected.items()):
            raise ValueError("approval evidence must bind exact source, candidate and placement")
        occupied.append(target)


def build_application_bundle(config: dict, compiled_input: dict | None, *, local_only: bool = False) -> dict:
    """Validate resident evidence and return a new deterministic, offline bundle."""
    if type(local_only) is not bool:
        raise ValueError("local_only must be an exact boolean")
    _object(config, _REQUIRED, _OPTIONAL)
    if len(_canonical(config)) > _MAX_JSON:
        raise ValueError("application config exceeds local size limit")
    if local_only:
        if compiled_input is not None:
            raise ValueError("local-only preservation cannot accept provider input")
    else:
        _object(compiled_input, {"source_video", "compiled_prompt"})
        url = urlsplit(_text(compiled_input["source_video"]))
        if url.scheme != "https" or not url.hostname or url.username or url.password:
            raise ValueError("source reference must be HTTPS without embedded credentials")
        _text(compiled_input["compiled_prompt"])
    cfg = copy.deepcopy(config)
    for key in ("audio", "candidates", "inserts", "historical_receipts"):
        cfg.setdefault(key, [])
        if not isinstance(cfg[key], list):
            raise ValueError("bundle collections must be lists")
    if local_only and (cfg["candidates"] or cfg["inserts"]):
        raise ValueError("local-only preservation cannot contain candidates or inserts")
    tracks = _snapshot(cfg["baseline"])
    _binding(cfg["source"], tracks, cfg["baseline"])
    audio_keys = [_binding(item, tracks, cfg["baseline"], audio=True) for item in cfg["audio"]]
    expected_audio = {(t, i) for t, clips in tracks.items() if t.startswith("audio")
                      for i in range(len(clips))}

View on GitHub (pinned to 8321021c54)