---
title: Stop Sportradar kickoff events matching the wrong play
type: task
status: completed
description: >-
  Sportradar kickoff slots on the wrong play were residue from an older matcher; the inverted
  possession swap, the two-events-one-row overwrite and the tracking feed down 0 were fixed and the
  residue repaired.
base_uri: user:task/league/stop-sportradar-kickoffs-matching-the-wrong-play.md
created_at: '2026-10-08T18:28:28.445Z'
entity_id: 35cef360-bf5e-4722-9f26-33f38c63e118
finished_at: '2026-10-08T22:48:27.295Z'
observations:
  - ████████████████████████████████████████████████
owner_identity_uri: █████████████████████████
priority: High
public_read: true
relations:
  - relates [[██████████████████████-██████-██████-██████████]]
  - relates [[███████████████████████-██████████-████-███████████]]
started_at: '2026-10-08T22:00:11.414Z'
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-10-08T22:48:33.023Z'
visibility_analyzed_at: '2026-11-06T00:18:06.464Z'
---

Kickoff slots that landed on the wrong play were residue from an older Sportradar matcher, not from the current one. The possession swap the plan meant to key on was inverted, and the measurement surfaced a live overwrite path and a tracking-feed coercion. All are fixed; the operator approved the revised scope on 2026-10-08.

## What was found

- **The current matcher was sound for kickoffs.** Over every cached payload (2024 REG, 2025 REG and POST, 2026 REG; no preseason game carries a Sportradar id) it agreed with every stored id.
- **The kickoff possession swap from league f4adca29e inverted a correct value.** Sportradar names the kicking team on 6,391 of 6,391 kickoffs. Its evidence, 156 2024-preseason rows, never had a Sportradar writer; their real writer is still unidentified. No stored damage: possession and the yard-line columns are protected fill-only fields.
- **Wrong-match residue, 18 rows, all from 2025 week 1:** seven timeout markers carrying a whole kickoff, two extra points carrying the next kickoff, 2025090400 play 1271 carrying Shipley's recovery, and nine rows with a penalty, pocket time or tackle value from another event.
- **A live overwrite path.** Two events could match one row and the later one overwrote it. 2025092802 play 2101 (a four-yard run) had been overwritten by the 1:18 holding run, clock included, which kept the wrong event matching.
- **The tracking feed stored down 0 and distance 0** on 10,872 kickoffs, extra points, conversions and markers in 2025-2026, which also left 160 stored Sportradar ids unreachable.
- **2025110908 play 423 is not misplaced.** Only Sportradar charted Knight's muff; the NFL text and GSIS omit it. **2025091407 play 3004** is a real kicking-team recovery.

## Plan

- [x] Measure the class across every covered season.
- [x] Fix the matcher: remove the possession swap (spec from a real cached kickoff, fails against the swap); drop the category-guessed `fumble_recovered_team`; one row, one event (`resolve_row_claims` refuses every claimant of a contested row); kickoffs fall back to nullified plays only, never an administrative marker. No team keys: 0 ambiguous kickoffs, and they would unmatch inverted onside rows. League 9289ddbe9, 9e3b2afc7.
- [x] Repair through dry-run-first files (each rehearsed with a forced rollback): `2026-10-08-clear-sportradar-wrong-match-residue.sql` (139 values, logged), `2026-10-08-restore-play-overwritten-by-wrong-sportradar-match.sql` (play 2101, 18 columns, logged), `2026-10-08-null-down-and-distance-zeros.sql` (writer fixed in the play-feed importer module), and a corrected possession column comment.
- [x] Containment check: `LOOSE_BALL_EVENT` admits "RECOVERED by"; a cell with a `play_field_override` is not a contradiction; play 423 carries overrides on its four recovery columns. The check's recovery-slot and `kickoff_yards` rows read 0 in every season, and the registry text says so.

## Found here, not fixed here

- `is_qb_hit`/`is_qb_hurry` false on about 29,000 matched rows, and `yards_after_any_contact` and zero broken-tackle values that the current mapper no longer writes for those events.
- The 2026-05-24 historical backfill overwrote `game_clock_start` on 14,437 plays; on some Sportradar rows the official clock was replaced by Sportradar's (2025090703 play 2665: 6:09 became 5:55).
- 2063 administrative markers carry `missed`/`missed`/`failure` kick results, a slice of user:task/league/fix-sportradar-2025-kick-result-enum-defaults.md.
- 2025092105 play 3600, a blocked field goal followed by a pass, was re-typed PASS by play enrichment on 2026-10-08, so its stored Sportradar id is unreachable.
- Six contested rows now report CLAIM_CONFLICT on re-import and are left as they stand; each is correct today.
