affaan-m/ECC · critical · ContractError
manifest crosses the dry-run boundary
Error message
{modality} manifest crosses the dry-run boundary What it means
Manifests must stay strictly inside the dry-run boundary: dry_run=true, submit=false, provider_calls exactly int 0, and provider_execution=false at the manifest level. Any violation raises this ContractError to prevent accidental paid provider execution.
Solutions
- Set dry_run=true, submit=false, provider_execution=false, and provider_calls=0 (integer) on the manifest.
- Change provider_calls to an int, not a string or bool — the check uses type(...) is not int so bools and strings are rejected.
- Review why the manifest crossed the boundary: if real provider execution is intended, it does not belong in a dry-run bundle and must go through a separate approval path.
- Regenerate the manifest from the dry-run template to restore safe defaults.
Example fix
// before
{"modality": "image", "dry_run": false, "submit": true, "provider_calls": 2, "provider_execution": true, "requests": [...]}
// after
{"modality": "image", "dry_run": true, "submit": false, "provider_calls": 0, "provider_execution": false, "requests": [...]} Defensive patterns
Strategy: validation
Validate before calling
def within_dry_run_boundary(payload):
return (payload.get("dry_run") is True
and payload.get("submit") is False
and type(payload.get("provider_calls")) is int
and payload.get("provider_calls") == 0
and payload.get("provider_execution") is False) Type guard
def is_dry_run_manifest(payload: dict) -> bool:
return (isinstance(payload.get("provider_calls"), int)
and not isinstance(payload.get("provider_calls"), bool)
and payload.get("dry_run") is True
and payload.get("submit") is False
and payload.get("provider_calls") == 0
and payload.get("provider_execution") is False) Try / catch
try:
validate_manifests(manifests_dir)
except ContractError as e:
if "dry-run boundary" in str(e):
logger.critical("manifest requests real provider execution — refusing to validate; review before any live run")
raise SystemExit(1) # do not auto-fix safety boundary violations
raise Prevention
- Never flip dry_run/submit flags to test real generation — use a separate reviewed live-run pipeline.
- Keep provider flags controlled by config with safe defaults, not hand-edited JSON.
- Watch for serialization turning int 0 into '0' or bool — re-check types after round-trips.
- Add a CI gate that fails any manifest with submit=true or provider_calls != 0.
When it happens
Trigger: A manifest with dry_run=false, submit=true, provider_calls=3, provider_calls='0' (string instead of int), provider_calls=true (bool — type() check rejects bools), or provider_execution=true in validate_manifests.
Common situations: Flipping dry_run to false to 'just test real generation' before review; leaving submit=true from a previous real run; YAML/JSON round-trip converting 0 into a string or bool; a generator defaulting provider_execution to true; copying a live-run config into the manifest.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- request crosses the dry-run boundary
- ECC_DRY_RUN must be "1" or "0" when set
- effect recipe crosses the dry-run provider boundary
- fal call failed after one attempt; job acceptance may be…
- genre crosses the dry-run boundary
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/943aa0aeffd9a533.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:296
)
def validate_manifests(manifests_dir: str | Path) -> None:
"""Require image, video, and 3D-asset dry-run request manifests."""
manifests_dir = Path(manifests_dir)
found = {path.stem for path in manifests_dir.glob("*.json")} if manifests_dir.is_dir() else set()
missing = _REQUIRED_MODALITIES - found
if missing:
raise ContractError(f"missing modality manifests: {sorted(missing)}")
for modality in _REQUIRED_MODALITIES:
payload = json.loads((manifests_dir / f"{modality}.json").read_text(encoding="utf-8"))
if payload.get("modality") != modality or not payload.get("requests"):
raise ContractError(f"invalid or empty {modality} manifest")
if (payload.get("dry_run") is not True or payload.get("submit") is not False
or type(payload.get("provider_calls")) is not int
or payload.get("provider_calls") != 0
or payload.get("provider_execution") is not False):
raise ContractError(f"{modality} manifest crosses the dry-run boundary")
for request in payload["requests"]:
if (request.get("dry_run") is not True
or request.get("submit") is not False
or type(request.get("provider_calls")) is not int
or request.get("provider_calls") != 0
or request.get("provider_execution") is not False
or request.get("provider_call_mode") != "disabled"):
raise ContractError(f"{modality} request crosses the dry-run boundary")
def validate_artifact_receipt(out_dir: str | Path, receipt: dict[str, Any]) -> None:
"""Verify that the receipt binds every emitted artifact and its provenance."""
out_dir = Path(out_dir).resolve()
entries = receipt.get("evidence_artifacts")
if not isinstance(entries, list):
raise ContractError("receipt evidence_artifacts must be a list")
if not all(isinstance(entry, dict) for entry in entries):
raise ContractError("receipt evidence_artifacts entries must be objects")View on GitHub (pinned to 8321021c54)