mvanhorn/last30days-skill · warning · KeyError

Polymarket event is closed, unavailable, or malformed

Error message

Polymarket event is closed, unavailable, or malformed

What it means

KeyError raised when the Gamma event was found but parse_polymarket_response produced no items from it. The parse uses include_closed=not has_active, so this fires when the event exists yet contains no markets matching the active/closed filter - i.e. it is closed, unavailable, or its markets array is malformed.

Source

Thrown at skills/last30days/scripts/lib/polymarket.py:1017

            event = None
    if not isinstance(event, dict):
        raise KeyError("Polymarket event was not found")
    # Mixed events: an active event can carry resolved child markets whose
    # high volume would win the parse and swap the outcome labels. Only fall
    # back to closed markets when nothing is active (fully resolved event -
    # the stale-odds transition verification exists to catch).
    markets = event.get("markets") or []
    has_active = any(
        isinstance(m, dict) and m.get("active", True) and not m.get("closed", False)
        for m in markets
    )
    parsed = parse_polymarket_response(
        {"events": [event]},
        include_all_outcomes=True,
        include_closed=not has_active,
    )
    if not parsed:
        raise KeyError("Polymarket event is closed, unavailable, or malformed")
    refreshed = parsed[0]
    values: dict[str, Any] = {}
    outcome_pairs = refreshed.get("outcome_prices") or []
    outcome_totals: dict[str, int] = {}
    for name, _price in outcome_pairs:
        normalized = str(name).casefold()
        outcome_totals[normalized] = outcome_totals.get(normalized, 0) + 1
    outcome_counts: dict[str, int] = {}
    for name, price in outcome_pairs:
        normalized = str(name).casefold()
        occurrence = outcome_counts.get(normalized, 0)
        outcome_counts[normalized] = occurrence + 1
        key = f"{name}\x1f{occurrence}" if outcome_totals[normalized] > 1 else str(name)
        values[key] = price
    if refreshed.get("end_date") is not None:
        values["end_date"] = refreshed["end_date"]

    if datum_key == "end_date":

View on GitHub (pinned to c7460f6114)

Solutions

  1. Catch KeyError and present the last known value with an 'event closed' note instead of failing the whole verification pass
  2. Skip re-verification for events whose updatedAt is old relative to the original fetch
  3. For genuinely closed events, route users to the resolution outcome rather than odds

Example fix

# before
refreshed = refetch_datum(item, "Yes")

# after
try:
    refreshed = refetch_datum(item, "Yes")
except KeyError:
    return {"value": cached_value, "stale": True, "note": "event closed or unavailable"}
Defensive patterns

Strategy: fallback

Try / catch

try:
    datum = refetch_datum(item, key)
except KeyError as e:
    if "closed, unavailable, or malformed" in str(e):
        datum = {"value": cached_value, "stale": True}

Prevention

When it happens

Trigger: Event dict whose markets list is empty or non-dict entries only (has_active False, include_closed True, still nothing parses); event fully resolved whose child markets fail the closed-market parsing; event with active=True markets that are all closed=True so they are excluded when has_active is False.

Common situations: Re-verifying odds on a market that resolved between original fetch and refresh; Gamma returning events with markets stripped out; schema drift in Gamma market fields breaking the parser.

Understand the failure class

Related errors


AI-assisted analysis of mvanhorn/last30days-skill@c7460f6114 (2026-08-15). Data as JSON: /api/errors/4bebc466d667d49a. Report an issue: GitHub.