---
title: Attach an external league mirror's next season automatically
type: task
status: planned
description: >-
  Nothing creates a mirror's next-season connection, so after a rollover the scheduler stops syncing
  it and the mirror freezes at its last season. Make the mirror sync scheduler find the renewed
  season (ESPN same id, Sleeper successor by previous_league_id) and attach it through
  import_season_chain.
base_uri: user:task/league/attach-external-league-mirror-next-season.md
created_at: '2026-10-02T00:01:39.998Z'
entity_id: 290aa939-079e-4d3c-bfcd-b2bc53776805
owner_identity_uri: █████████████████████████
priority: Medium
public_read: true
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-10-02T00:01:39.998Z'
visibility_analyzed_at: '2026-11-05T23:48:23.534Z'
---

# Attach a Mirror's Next Season Automatically

## Problem

A mirror connection is one season of an external league. Nothing creates next season's connection: a new ESPN season becomes a connection only when someone re-imports (POST /import attaches it), and a renewed Sleeper league gets a new league id that nothing discovers. The scheduler excludes a synced past-season connection (`scripts/schedule-external-league-mirror-syncs.mjs`, `past_season_synced`), so after a rollover a mirror silently stops syncing and freezes at its last season.

## Decision

Decided 2026-10-01 while closing [[███████████████████████-████████-██████-████-███████-██-██████████]]: the scheduler attaches a mirror's next season itself. Re-import is not a user's job, and a frozen mirror reads as a healthy one.

## Plan

- [ ] For each mirror whose newest connection's `season_year` is behind the season the vendor now serves, probe for the successor during the scheduler run.
  - ESPN: one league id serves every season, so the successor is the same id at `seasonId = newest + 1`; a 404 means not renewed yet.
  - Sleeper: the successor is the league whose `previous_league_id` is the newest connection's id. Find it by listing a member's leagues for the next season (`/user/{user_id}/leagues/nfl/{season}`), reusing the member ids the mirror already holds.
- [ ] Attach the successor through `import_season_chain` (`libs-server/external-fantasy-leagues/import-season-chain.mjs`), so it gets the same chain root and a queued sync, exactly as POST /import attaches a season.
- [ ] Report probes in the scheduler's run summary (attached, not yet renewed, probe failed), and signal on a failed probe per the pipeline-failure guideline.
- [ ] Specs: ESPN and Sleeper successor found and attached; not-yet-renewed attaches nothing; a second run is a no-op.
- [ ] Verify against the first real rollover: lid 121 and 123 (Sleeper) renew around January 2027, and lid 122 (ESPN) when its manager renews.
