# Family Waters Bonus + Join League Fix (Jul 9, 2026) ## Changes ### 1. Join League 500 Error Fix **Root cause:** `sqlite3.Row` has no `.get()` method. The `join_league` endpoint at line 584 called `league.get("max_players")` on a `sqlite3.Row` object. **Fix:** Added `league = dict(league)` after `fetchone()` but before accessing values. ```python # Before: league = conn.execute("SELECT * FROM leagues WHERE invite_code = ?", (code,)).fetchone() if league["status"] != "draft": # works because bracket access IS supported on sqlite3.Row ... max_p = league.get("max_players") or 6 # AttributeError - sqlite3.Row has no .get() # After: league = conn.execute("SELECT * FROM leagues WHERE invite_code = ?", (code,)).fetchone() if not league: raise HTTPException(404, "Invalid invite code") league = dict(league) # <--- THE FIX if league["status"] != "draft": ... max_p = league.get("max_players", 6) # now works, and uses the default arg properly ``` **Lesson:** Compare with `get_league_or_404()` helper that already does `dict(league)`. The join endpoint was the only place that skipped this conversion. ### 2. Family Waters +30 Bonus **New feature:** Score events can be marked personal (`is_personal: true`) to earn +30 bonus points. **API change:** ``` POST /api/scores/events { "region_id": 1, "event_type": "bite", "is_personal": true ← new } → { "points": 35, "family_waters_bonus": 30, "is_personal": true, ... } ``` **Leaderboard change:** ```json { "user_id": 34, "display_name": "HostUser", "total_points": 52, "family_waters_bonus": 60, "family_waters_count": 2, "regions": [...] } ``` **Push notification format change:** ``` "+5 pts + 30 Family Waters — 🏖️ Florida East Coast" (vs normal: "+5 pts — 🏖️ Florida East Coast") ``` **Migration SQL (run in `on_startup`):** ```python conn.execute("ALTER TABLE scores ADD COLUMN is_personal INTEGER DEFAULT 0") conn.execute("ALTER TABLE users ADD COLUMN family_waters_bonus INTEGER DEFAULT 0") conn.execute("ALTER TABLE users ADD COLUMN family_waters_count INTEGER DEFAULT 0") ``` **Key files changed:** `server.py` only — CreateScoreEvent model, create_score_event endpoint, recalculate_user_scores helper, leaderboard query, push notification body builder.