When a simulation action threw (e.g. readiness check failure), React Router
tried to render the simulate route via GET to display the error — but the
route had no loader, so the real error was completely swallowed by React
Router's own 400 "no loader" message.
Four issues fixed:
- Move simulate into the intent-dispatch pattern on the season page (matching
delete/rescore/sync-standings/finalize-standings), so errors surface via
actionData instead of being lost
- Eliminate the ?simulationError= query param approach, which left stale error
messages in browser history and reflected user-controlled text in the UI
- Match the existing bg-destructive/15 error styling used elsewhere on the page
- Strip the now-unused action from simulate.tsx; keep a loader-only redirect
stub so any bookmarked URLs degrade gracefully to the season page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>