Declining a remote invite could show a raw 'MatrixError: [500] Internal server error' and appear to do nothing. Root causes were client-side: decline called mx.leave unconditionally, so re-clicking after a slow federated leave hit an already-left remote room that Synapse 500s on; the room was never forgotten so a 'leave' ghost lingered and re-invited a click; and the raw error string was shown. Add a shared declineInvite(mx, roomId) helper that only leaves when still in the room (invite/join/knock) and then forgets it (best-effort, first use of forget in the app). Route the InviteCard decline and both 'Decline All' paths through it, and replace the raw error with a friendly message (real error kept in console). Tests: declineInvite covered (6 cases); typecheck + full suite + build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>