{"record":{"id":"af3f45c6aeeed50d","repo":"mvanhorn/last30days-skill","slug":"polymarket-datum-datum-key-r-was-not-found","errorCode":null,"errorMessage":"Polymarket datum {datum_key!r} was not found","messagePattern":"Polymarket datum (.+?) was not found","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"skills/last30days/scripts/lib/polymarket.py","lineNumber":1050,"sourceCode":"    if refreshed.get(\"end_date\") is not None:\n        values[\"end_date\"] = refreshed[\"end_date\"]\n\n    if datum_key == \"end_date\":\n        value = values.get(\"end_date\")\n    else:\n        if \"\\x1f\" in datum_key:\n            outcome_name, raw_occurrence = datum_key.rsplit(\"\\x1f\", 1)\n            occurrence = int(raw_occurrence)\n        else:\n            outcome_name, occurrence = datum_key, 0\n        matches = [\n            price\n            for name, price in refreshed.get(\"outcome_prices\") or []\n            if str(name).casefold() == outcome_name.casefold()\n        ]\n        value = matches[occurrence] if occurrence < len(matches) else None\n    if value is None:\n        raise KeyError(f\"Polymarket datum {datum_key!r} was not found\")\n    return {\n        \"value\": value,\n        \"values\": values,\n        \"url\": str(getattr(item, \"url\", \"\")),\n        \"timestamp\": event.get(\"updatedAt\"),\n    }\n","sourceCodeStart":1032,"sourceCodeEnd":1057,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/skills/last30days/scripts/lib/polymarket.py#L1032-L1057","documentation":"KeyError raised when the requested datum key (outcome name, optionally with a \\x1f occurrence suffix for duplicate outcome labels) does not match any outcome in the refreshed event's outcome_prices list. Casefolded comparison is used, and occurrence indexing handles repeated labels like multiple 'Yes' markets.","triggerScenarios":"refetch_datum(item, datum_key) where datum_key names an outcome ('Yes', 'No', custom label) absent from refreshed['outcome_prices']; or the occurrence number (after \\x1f split) exceeds the count of casefolded matches, so matches[occurrence] would be out of range and value stays None.","commonSituations":"Event outcome labels renamed between original fetch and refresh (e.g. a candidate dropping out relabels markets); datum keys built against an older parse of the event; multi-market events where the number of same-labeled outcomes shrank.","solutions":["Re-derive datum keys from the refreshed outcome_prices list rather than reusing keys from the original parse","Catch KeyError and fall back to listing available outcome names so the caller can re-select","For multi-occurrence keys, clamp the occurrence index to len(matches) - 1 when exact occurrence no longer exists"],"exampleFix":"# before\nvalue = refetch_datum(item, \"Yes\\x1f2\")  # KeyError if only 1 'Yes' left\n\n# after\nmatches = [n for n, _ in refreshed_outcomes if n.casefold() == \"yes\"]\nkey = \"Yes\" if len(matches) == 1 else f\"Yes\\x1f{min(2, len(matches)-1)}\"\nvalue = refetch_datum(item, key)","handlingStrategy":"try-catch","validationCode":"def datum_key_exists(refreshed_outcomes, datum_key: str) -> bool:\n    if \"\\x1f\" in datum_key:\n        name, occ = datum_key.rsplit(\"\\x1f\", 1)\n        occ = int(occ)\n    else:\n        name, occ = datum_key, 0\n    matches = [n for n, _ in refreshed_outcomes or [] if str(n).casefold() == name.casefold()]\n    return occ < len(matches)","typeGuard":null,"tryCatchPattern":"try:\n    value = refetch_datum(item, datum_key)\nexcept KeyError as e:\n    if \"datum\" in str(e):\n        available = [n for n, _ in refreshed_outcomes]\n        reselect_outcome(available)","preventionTips":["Re-derive datum keys from the refreshed outcome list each verification cycle","Clamp occurrence suffixes to the current number of same-labeled outcomes","Store the outcome label plus event id, not positional assumptions"],"tags":["polymarket","keyerror","outcomes","data-drift"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}