paperclipai/paperclip · error · ValueError
Missing campaign coverage flag
Error message
Missing campaign coverage flag
What it means
Every campaign must carry a boolean `complete` flag indicating full vs partial coverage, which the page renders as 'Complete campaign' or 'Partial campaign'. If the key is missing or not a bool, summarize() refuses to guess and raises ValueError.
Solutions
- Re-publish the campaign with an explicit boolean `complete` field.
- Fix the producer to always set complete (true/false) on every campaign record.
- If consuming a legacy feed, migrate it: add `complete` derived from the run's selection coverage.
- Update offline fixtures in --history-dir to include complete: true/false.
Example fix
# before
{"campaignId": "c-1", "generatedAt": "..."} # no complete flag
# after
{"campaignId": "c-1", "generatedAt": "...", "complete": true} Defensive patterns
Strategy: validation
Validate before calling
def has_complete_flag(campaign):
return type(campaign.get("complete")) is bool Type guard
def has_bool_complete(campaign):
return type(campaign.get("complete")) is bool Try / catch
try:
values = summarize(history, kind)
except ValueError as e:
if str(e) == "Missing campaign coverage flag":
log.error("campaign missing boolean `complete`; migrate feed before building")
raise
raise Prevention
- Always set complete: true/false on every campaign record at publish time.
- Reject string/number booleans in the producer's serialization layer.
- Migrate legacy feeds to add the flag before pointing build.py at them.
- Include `complete` in fixture templates for tests.
When it happens
Trigger: A campaign entry lacking the `complete` key, or storing it as a string ('true'), int (1/0), or null — e.g. older feeds predating the flag, or a producer serializing the wrong type.
Common situations: Old history fixtures generated before the coverage flag was introduced; publisher bug omitting the field for resumed campaigns; schema drift between feed versions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- History has no latest campaign
- Report refresh has no reliable measurement date
- CreateOS requires a shape from its shape catalog.
- History date must include a timezone
- Invalid campaign counts
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/7a2122f865ec007b.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/evals-hub/build.py:58
return html.escape(url, quote=True)
def display_date(value):
date = datetime.fromisoformat(value.replace("Z", "+00:00"))
if date.tzinfo is None:
raise ValueError("History date must include a timezone")
return date.astimezone(timezone.utc).strftime("%d %b %Y · %H:%M UTC")
def summarize(history, kind):
prefix, schema = SYSTEMS[kind]
campaign = latest(history, schema)
totals = campaign["totals"] if kind == "runner" else campaign
passed, selected = totals["passed"], totals["selected"]
if any(type(n) is not int for n in (passed, selected)) or not 0 <= passed <= selected:
raise ValueError("Invalid campaign counts")
if type(campaign.get("complete")) is not bool:
raise ValueError("Missing campaign coverage flag")
revision = campaign.get("reportRevision", {})
if revision and not isinstance(revision.get("sourceGeneratedAt"), str):
raise ValueError("Report refresh has no reliable measurement date")
measured = revision.get("sourceGeneratedAt", campaign["generatedAt"])
return {
"url": public_report(campaign["publicUrl"], prefix),
"date": html.escape(display_date(measured)),
"counts": f"{passed} / {selected} selected cases passed",
"coverage": "Complete campaign" if campaign["complete"] else "Partial campaign",
"id": html.escape(revision.get("sourceCampaignId", campaign["campaignId"])),
}
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--history-dir", type=Path, help="Use saved public history JSON files for offline verification")
parser.add_argument("--docs-ref", default="master", help="Git ref containing doc/evals.md")View on GitHub (pinned to 3f1d897a7c)