This issue is indeed quite frustrating. Because the web client is constrained by the browser, sometimes newly initiated connections can get stuck in a pending state, as browsers limit the number of concurrent websocket connections. This is a major reason why messages fail to send. It tends to happen more often when you're browsing the following feed, since building that feed requires connecting to dozens or even hundreds of relays.
I remember adding a retry button for failed messages, but it seems like it’s not showing up? I’ll need to take a look.