Skip to content

feat(ScheduledMessages): handle failed scheduled messages (REACT-1390) - #3372

Draft
NikolaGoranNaumovski wants to merge 6 commits into
feat/react-1389-scheduled-messages-managefrom
feat/react-1390-scheduled-messages-failures
Draft

NikolaGoranNaumovski wants to merge 6 commits into
feat/react-1389-scheduled-messages-managefrom
feat/react-1390-scheduled-messages-failures

Conversation

@NikolaGoranNaumovski

@NikolaGoranNaumovski NikolaGoranNaumovski commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

🎯 Goal

Handle scheduled messages that fail to send, so a failure is never silent and the user can recover:

  • schedule a failed message again from the list;
  • get notified when a message fails;
  • see failures in the banner.

It also finishes the customisation story for the scheduled message UI with the remaining ComponentContext slots. This follows the web designs (Figma: Scheduled List → Row Menu (Failed), Failed Reasons; Confirmation → Failed).

Part of the scheduled messages feature (REACT-1390). Stacked on #3371 (manage actions). Depends on GetStream/stream-chat-js#1956 for MessageComposer.rescheduleFailedMessage.

🛠 Implementation details

Schedule a failed message again

  • The server rejects edits to failed messages (120), and re-sending the failed message.id returns the failed row. So Edit on a failed item opens it with composer.rescheduleFailedMessage(failedMessage). The composer is filled as a new composition with a fresh id, without edit mode.
  • The composer shows FailedScheduledMessagePreview ("Schedule again"), with a cancel button that restores the earlier draft. The schedule button stays available.
  • Scheduling it deletes the failed message (handled by MessageComposer). Sending it right away with Enter or Send also deletes the failed message.
  • openScheduledMessageInComposer(composer, scheduledMessage) picks edit or schedule-again by status. Both the banner's list and the Channel Detail section use it.
  • Row menu rules:
    • failed: Edit, Delete;
    • failed because the channel was deleted (channel_deleted): Copy, Delete (unchanged);
    • scheduled: Edit, Reschedule, Send now, Delete (unchanged).

Failure notification

  • Chat listens for scheduled_message.failed (sent only to the scheduling user while connected) and adds an error notification of type api:scheduled-message:send:failed, with the failure reason.
  • translateScheduledMessageSendFailed shows "Scheduled message not sent: ", using the same reason copy as the list. user_deleted adds no reason.
  • The listener is removed when Chat unmounts.

Failed count in the banner

  • The banner adds "N failed" after its count when messages in the channel or thread failed (useFailedScheduledMessageCount), with a str-chat__scheduled-messages-banner--failed modifier.
  • When the store is reset for another user (disconnectUser), the banner disappears.

Override slots (ComponentContext)

Slot Default Used by
ScheduledMessageList ScheduledMessageList banner list dialog, Channel Detail section
ScheduledMessageActions (null hides it) ScheduledMessageActions each list item
DeleteScheduledMessageAlert DeleteScheduledMessageAlert row menu → Delete
RescheduleMessageDialog RescheduleMessageDialog row menu → Reschedule
FailedScheduledMessagePreview FailedScheduledMessagePreview composer, while scheduling a failed message again

Translations
All new strings are in the 12 locales, including each locale's plural forms for "N failed".

Commits

  1. feat: schedule a failed message again
  2. feat: notify when a scheduled message fails to send
  3. feat: show the failed count in the banner
  4. feat: make the list, row actions and dialogs overridable
  5. feat(i18n): translations

Each commit typechecks and passes the scheduled-message, composer, Chat, Channel Detail and i18n tests on its own. The full suite passes on the last commit (3479 tests).

Testing

  • Unit:
    • Row menu actions per status, including failed.
    • openScheduledMessageInComposer for pending and failed messages.
    • In the composer:
      • the schedule-again preview;
      • the schedule button staying visible;
      • cancel restoring the draft;
      • sending now deleting the failed message.
    • The failure notification, and no notification after unmount.
    • The send-failed translator for a known, an unknown and a hidden reason.
    • The banner's failed count, its absence when nothing failed, and its reset.
    • One test per new slot.
    • axe checks for the banner in its failed state.
  • Live check (stream-chat-js): a message failed with channel_frozen after its channel was frozen. It was then scheduled again with rescheduleFailedMessage. The server kept only the new message, the failed one left the store, and the earlier draft came back.

Not in this PR

  • Public docs (CHA-5939).
  • UI copy is based on the Figma structure. The exact Figma text could not be read yet and will be aligned once it can.

🎨 UI Changes

Screenshots: banner with "1 failed", row menu for a failed message, "Schedule again" preview in the composer, failed-send notification.

A failed scheduled message cannot be edited, so Edit in its row menu now
opens it with MessageComposer.rescheduleFailedMessage: the composer is
filled as a new composition, shows a FailedScheduledMessagePreview
("Schedule again", overridable through ComponentContext) and can schedule
it from the schedule button. Scheduling deletes the failed message; cancel
restores the earlier draft. Sending it right away also deletes the failed
message.

openScheduledMessageInComposer picks edit or schedule-again by status for
the banner list and the Channel Detail section.

Refs: REACT-1390
Chat listens for scheduled_message.failed (sent only to the scheduling
user while connected) and adds an error notification of type
api:scheduled-message:send:failed with the failure reason. The new
translateScheduledMessageSendFailed shows "Scheduled message not sent"
with the reason copy used in the list; user_deleted adds no reason.

Refs: REACT-1390
The banner adds "N failed" after its count when scheduled messages in the
channel or thread failed (useFailedScheduledMessageCount), with a --failed
modifier for styling. Tests also cover the banner disappearing when the
store is reset for another user.

Refs: REACT-1390
…idable

Add ComponentContext slots used by the default components:
- ScheduledMessageList, for the banner's list dialog and the Channel Detail
  section
- ScheduledMessageActions, the actions button on each list item (null hides
  it)
- DeleteScheduledMessageAlert and RescheduleMessageDialog, opened from the
  row menu

Refs: REACT-1390
Translate the banner's failed count (with each locale's plural forms), the
schedule-again preview and the failed-send notification in all 12 locales.

Refs: REACT-1390
@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

…act-1390-scheduled-messages-failures

# Conflicts:
#	src/i18n/TranslationBuilder/notifications/translators.ts
#	src/i18n/__tests__/scheduledMessageNotificationTranslators.test.ts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant