Skip to content

[BUG] Tournament blockers #421

@Flegma

Description

@Flegma

Fix tournament blockers that can crash or hang bracket progression

6 verified bugs in the tournament SQL layer that can cause matches to not start, teams to get
double-assigned, or tournaments to hang indefinitely.

Bugs

1. Swiss pool double-assignment (Critical)
assign_teams_to_swiss_pools evaluates get_swiss_team_pools() once at loop start. Teams borrowed from
adjacent pools remain in the original pool's stale team_ids, causing one team to be assigned to two
matches in the same round.

  • File: api/hasura/functions/tournaments/assign_teams_to_swiss_pools.sql

2. Bracket slot overwrite on concurrent writes (High)
The fallback path in assign_team_to_bracket_slot uses a stale read and has no IS NULL guard on the
UPDATE. A concurrent bracket assignment can overwrite an existing team, removing it from the tournament.

  • File: api/hasura/functions/tournaments/assign_team_to_bracket_slot.sql

3. Non-deterministic stage seeding on tied rankings (High)
seed_stage uses OFFSET on v_team_stage_results. When teams have identical stats across all
tiebreakers, PostgreSQL returns them in arbitrary order. Re-running after pause/resume can swap teams
between bracket slots.

  • File: api/hasura/views/v_team_stage_results.sql

4. Silent scheduling failures hang tournaments (Medium)
schedule_tournament_match has 5 RETURN NULL paths with no logging. If any fires unexpectedly, the
bracket has teams but no match, and the tournament hangs with zero diagnostic output.

  • File: api/hasura/functions/tournaments/schedule_tournament_match.sql

5. Auto-forfeit awards win to wrong team (Medium)
CancelExpiredMatches.forfeitMatch() uses lineup_1.is_ready ? lineup_1 : lineup_2, silently forfeiting
to lineup_2 when neither team is ready.

  • File: api/src/matches/jobs/CancelExpiredMatches.ts

6. Orphaned brackets prevent tournament completion (Medium)
Brackets can get stuck with bye=false, finished=false, no teams, and no pending feeders.
check_tournament_finished counts them as unfinished, so the tournament never reaches Finished status.

  • File: api/hasura/functions/tournaments/check_tournament_finished.sql

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

Status

Ready

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions