Problem
When the channel data load fails, the feed shows its error, but the composer keeps showing a loading skeleton. On desktop, the participants list keeps its skeleton too. Both stay for as long as the error does.
On 14ab7f9c1. Paths are under apps/webapp/src/components/chatroom/.
isFeedReady is isChannelDataLoaded && !messagesLoading && !errorMsg (ChatroomContext.tsx:288). So a load error keeps it false.
- Only the channel data load sets that error. It is the
get_channel_aggregate_data RPC, called by useChannelMetadata. A failed message window does not set it (hooks/useChannelMessages.ts:75-86).
ChannelComposer renders ChatroomComposerSkeleton while isFeedReady is false (components/ChannelComposer/ChannelComposer.tsx:32-34).
ParticipantsList renders AvatarStackLoader skeleton faces while isFeedReady is false (components/ChatroomToolbar/components/ParticipantsList.tsx:17-23). Desktop mounts it in the chat toolbar.
MessageFeedError wraps the whole feed (components/MessageFeed/MessageFeed.tsx:53). On an error it renders only the badge "Error loading messages...". The feed skeleton and the ChatList both unmount (components/MessageFeed/components/FeedStates/MessageFeedError.tsx:10-16). The error state has no retry control.
The chatroom rules say the opposite: "On RPC error, skeletons drop with the error badge — no skeleton/error mismatch" (apps/webapp/src/components/chatroom/CLAUDE.md:132).
A skeleton means that content is loading. Next to an error, it makes the user wait for content that will not load.
Steps to reproduce
- Open a pad and open a heading chat.
- In DevTools, block requests that match
rpc/get_channel_aggregate_data. Close the chat and open it again.
- See the feed error, and a composer skeleton that stays.
Or open a pad link with ?chatroom=<heading id>&msg_id=<id of a deleted message>. The RPC then raises Anchor message … does not exist or has been deleted.
Acceptance criteria
Agent Brief
Category: bug
Summary: The composer and the participants list must leave their loading skeletons when the channel data load fails.
Current behavior:
One flag, isFeedReady, gates three skeletons: the feed, the composer, and the desktop participants list. It stays false on a load error. The feed switches to its error state, but the other two keep their skeletons.
Desired behavior:
A load error ends the composer's loading state too. The error wins over loading. After the error, the message load can stay pending until the chat closes. The composer then shows no text field and no skeleton. It must not stay usable. The error state unmounts the message list. A send would still save the message, but the feed would not show it.
Key interfaces:
isFeedReady and error on the ChatroomContext value.
ChannelComposer.AccessControl — chooses between the skeleton, the join prompts, and the composer.
ChatroomComposerSkeleton.
ParticipantsList — the desktop chat toolbar avatars.
MessageFeedError — the feed error state.
Out of scope
- The feed error state itself, its copy, and a retry control.
- Retry logic for the channel data load.
- A usable composer while the load error shows.
Notes
The evidence is a code trace on 14ab7f9c1, confirmed by two verifiers and one reviewer. It was not reproduced in a browser.
Problem
When the channel data load fails, the feed shows its error, but the composer keeps showing a loading skeleton. On desktop, the participants list keeps its skeleton too. Both stay for as long as the error does.
On
14ab7f9c1. Paths are underapps/webapp/src/components/chatroom/.isFeedReadyisisChannelDataLoaded && !messagesLoading && !errorMsg(ChatroomContext.tsx:288). So a load error keeps it false.get_channel_aggregate_dataRPC, called byuseChannelMetadata. A failed message window does not set it (hooks/useChannelMessages.ts:75-86).ChannelComposerrendersChatroomComposerSkeletonwhileisFeedReadyis false (components/ChannelComposer/ChannelComposer.tsx:32-34).ParticipantsListrendersAvatarStackLoaderskeleton faces whileisFeedReadyis false (components/ChatroomToolbar/components/ParticipantsList.tsx:17-23). Desktop mounts it in the chat toolbar.MessageFeedErrorwraps the whole feed (components/MessageFeed/MessageFeed.tsx:53). On an error it renders only the badge "Error loading messages...". The feed skeleton and theChatListboth unmount (components/MessageFeed/components/FeedStates/MessageFeedError.tsx:10-16). The error state has no retry control.The chatroom rules say the opposite: "On RPC error, skeletons drop with the error badge — no skeleton/error mismatch" (
apps/webapp/src/components/chatroom/CLAUDE.md:132).A skeleton means that content is loading. Next to an error, it makes the user wait for content that will not load.
Steps to reproduce
rpc/get_channel_aggregate_data. Close the chat and open it again.Or open a pad link with
?chatroom=<heading id>&msg_id=<id of a deleted message>. The RPC then raisesAnchor message … does not exist or has been deleted.Acceptance criteria
Agent Brief
Category: bug
Summary: The composer and the participants list must leave their loading skeletons when the channel data load fails.
Current behavior:
One flag,
isFeedReady, gates three skeletons: the feed, the composer, and the desktop participants list. It stays false on a load error. The feed switches to its error state, but the other two keep their skeletons.Desired behavior:
A load error ends the composer's loading state too. The error wins over loading. After the error, the message load can stay pending until the chat closes. The composer then shows no text field and no skeleton. It must not stay usable. The error state unmounts the message list. A send would still save the message, but the feed would not show it.
Key interfaces:
isFeedReadyanderroron theChatroomContextvalue.ChannelComposer.AccessControl— chooses between the skeleton, the join prompts, and the composer.ChatroomComposerSkeleton.ParticipantsList— the desktop chat toolbar avatars.MessageFeedError— the feed error state.Out of scope
Notes
The evidence is a code trace on
14ab7f9c1, confirmed by two verifiers and one reviewer. It was not reproduced in a browser.