Describe the bug
When sending a room message fails — due to a network error, a 429 rate-limit response, or a 500 server error — `MessageInput.tsx` silently resets the sending state and does nothing else. The user's typed message disappears from the textarea with no indication that anything went wrong.
```ts
// src/components/rooms/MessageInput.tsx
setSending(false);
if (res.ok) {
const message = await res.json();
onSent(message);
setContent('');
}
// No else branch. No error state. No toast.
// The user's message is lost silently.
```
The `catch` block for network-level errors has the same problem — it also does nothing.
Steps to reproduce
- Open a collaboration room.
- Throttle the network to offline in browser DevTools.
- Type a message and press Enter or click Send.
- Observe: the textarea clears, the spinner disappears, and no error is shown.
Alternatively, the same silent failure occurs if the server returns a 429 or 500.
Expected behaviour
When a send fails, the user should:
- See an error message (inline below the textarea or as a toast notification).
- Have their original message text preserved in the textarea so they can retry without re-typing.
Files affected
- `src/components/rooms/MessageInput.tsx` (lines 18–34) — missing error branch
Suggested fix
```tsx
const [error, setError] = useState<string | null>(null);
// In handleSend:
setSending(false);
if (res.ok) {
const message = await res.json();
onSent(message);
setContent('');
setError(null);
} else {
const data = await res.json().catch(() => ({}));
setError(data?.error ?? 'Failed to send message. Please try again.');
// Do NOT clear content so the user can retry.
}
// In the catch block:
} catch {
setSending(false);
setError('Network error. Check your connection and try again.');
}
```
Render the error below the textarea:
```tsx
{error && (
{error}
)}
\`\`\`
Alternatively, use the project's existing Sonner toast (`import { toast } from 'sonner'`) to show a non-blocking error notification — matching the pattern used elsewhere in the dashboard.
Additional context
`CreateRoomModal.tsx` in the same feature area handles errors correctly with a `setError` state and an inline error paragraph. `MessageInput.tsx` should follow the same pattern for consistency.
Describe the bug
When sending a room message fails — due to a network error, a 429 rate-limit response, or a 500 server error — `MessageInput.tsx` silently resets the sending state and does nothing else. The user's typed message disappears from the textarea with no indication that anything went wrong.
```ts
// src/components/rooms/MessageInput.tsx
setSending(false);
if (res.ok) {
const message = await res.json();
onSent(message);
setContent('');
}
// No else branch. No error state. No toast.
// The user's message is lost silently.
```
The `catch` block for network-level errors has the same problem — it also does nothing.
Steps to reproduce
Alternatively, the same silent failure occurs if the server returns a 429 or 500.
Expected behaviour
When a send fails, the user should:
Files affected
Suggested fix
```tsx
const [error, setError] = useState<string | null>(null);
// In handleSend:
setSending(false);
if (res.ok) {
const message = await res.json();
onSent(message);
setContent('');
setError(null);
} else {
const data = await res.json().catch(() => ({}));
setError(data?.error ?? 'Failed to send message. Please try again.');
// Do NOT clear content so the user can retry.
}
// In the catch block:
} catch {
setSending(false);
setError('Network error. Check your connection and try again.');
}
```
Render the error below the textarea:
```tsx
{error && (
{error}
)} \`\`\`Alternatively, use the project's existing Sonner toast (`import { toast } from 'sonner'`) to show a non-blocking error notification — matching the pattern used elsewhere in the dashboard.
Additional context
`CreateRoomModal.tsx` in the same feature area handles errors correctly with a `setError` state and an inline error paragraph. `MessageInput.tsx` should follow the same pattern for consistency.