RocketChat / RocketChat/Rocket.Chat
Livechat widget: thread rendering throws when a parent message can't be fetched (unguarded destructures)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 46.1k
- Forks
- 13.9k
- Avg merge
- 3d 3h
- Merged PRs (30d)
- 130
Description
Description:
In the Livechat widget, thread-reply messages resolve their quoted-parent context via normalizeThreadMessage in packages/livechat/src/lib/threads.ts. When the parent message can't be fetched, two unguarded operations make rendering throw instead of degrading gracefully:
Bug A — findParentMessage catch block re-throws (lines 43-45):
} catch (error: any) {
const {
data: { error: reason }, // TypeError when `error.data` is undefined
} = error;
Livechat.message() rejects with a plain network/timeout error (no .data payload) on connection failures. Destructuring data: { error } from such an error throws a new TypeError inside the catch block, swallowing the original error and skipping the intended user-facing alert.
Bug B — normalizeThreadMessage destructures a possibly-undefined parent (line 62):
parentMessage = await findParentMessage(message.tmid); // undefined when the fetch failed
const { msg, attachments = [] } = parentMessage; // TypeError: Cannot destructure property 'msg' of 'undefined'
Even when Bug A doesn't fire (an HTTP error that does carry .data), findParentMessage returns undefined, and line 62 crashes destructuring it.
Steps to reproduce:
- Enable Livechat and open the widget as a visitor.
- Have an agent reply to a message in a thread (so the visitor's history contains a message with
tmidwhose parent is not in the current batch). - Trigger a failed parent fetch — e.g. block/offline the
Livechat.messagerequest, or delete the parent message server-side, then reload the widget history (loadMessages). - The message list fails to render instead of showing the reply without its quoted context.
Expected behavior:
When a thread's parent message can't be loaded, the widget should still render the reply (without the quoted-parent preview) and/or show the graceful alert — never throw.
Actual behavior:
An unhandled TypeError is thrown from threads.ts (either the catch-block destructure or the parentMessage destructure), breaking message rendering.
Server Setup Information:
- Version of Rocket.Chat Server:
develop(client-side bug in@rocket.chat/livechat; server-version independent)
Client Setup Information:
- Rocket.Chat Livechat widget (
@rocket.chat/livechat), any browser.
Additional context
Distinct from #42002 (which fixes the normalizeMessages async-filter no-op). This is a separate error-handling defect in the same file; the open PR #42089 does not touch these lines.
Proposed fix (minimal guards):
// Bug A — findParentMessage catch
const reason = error?.data?.error ?? error?.message ?? 'Could not load message';
// Bug B — normalizeThreadMessage
if (!parentMessage) {
return message; // render the reply without quoted context
}
I'd like to work on this and will open a PR.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/livechat/src/lib/threads.ts, reading findParentMessage and normalizeThreadMessage and following their use during loadMessages. Reproduce a failed Livechat.message request, then verify the reply still renders without quoted-parent context and that the intended graceful alert is preserved rather than a TypeError being thrown.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100