Conversation
When importing an identity, the room is created with a default ChatRoomStateV1 that has an unsigned configuration. The sync process then tries to PUT this invalid state to the contract, which fails because the configuration signature doesn't verify (only the room owner can sign it). Since the PUT fails, the subscription is never established, leaving the user stuck with default state. All subsequent message UPDATEs also fail with "Invalid signature: signature error". Fix: detect imported rooms (empty state, non-owner) and send a GET request first to retrieve the real state from the network. When the GET response arrives, PUT the valid state with subscribe=true to register the contract code and establish the subscription. Closes #188 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace pre-computed Vec of rooms needing GET-first with inline check per iteration, eliminating a separate collection pass and O(n) lookup - Flatten needs_put_subscribe detection from a block with intermediate variables to a chained expression - Standardize error log prefix to "Failed to send" for consistency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GlobalSignal writes must be deferred to avoid RefCell re-entrancy panics per Dioxus WASM signal safety rules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move mark_initial_sync_complete and signing key migration inside PUT success path so they don't fire on PUT failure - Use SYNC_INFO.with_mut() instead of .write() in error defer - Reset to Disconnected on PUT failure for automatic retry (after GET+merge the state is valid, so retry takes normal PUT path) - Add mark_needs_sync after successful PUT to persist state to delegate - Add comment explaining why PUT uses retrieved_state (not merged state) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a user imports an identity (export → leave room → import), the room is created with a
ChatRoomStateV1::default()that has an unsigned configuration. The sync process tries to PUT this invalid state to the contract, which fails with "State verification failed: Invalid signature: signature error" because only the room owner can sign the configuration. Since the PUT fails, the subscription is never established, and the user is stuck in an infinite loop of failed PUT retries with the same invalid default state. All subsequent message UPDATEs also fail.Diagnostic report UF32XU confirms this: the first error is a PUT failure at 11:53:16, followed by repeated UPDATE failures, all with the same "Invalid signature" error on configuration validation.
Approach
For rooms awaiting subscription, detect "fresh imports" using the existing
is_awaiting_initial_sync()method (empty members + empty messages + user is not owner). For these rooms:subscribe: trueto register the contract code and establish the subscriptionThis mirrors the existing invitation flow (which also does GET-first) but for the import path.
Testing
cargo test -p river-core— all passcargo test -p chat-delegate— all passcargo checkfor UI compiles cleanly (only pre-existing CSS asset warning)ui/code modified, no delegate migration neededChanges
room_synchronizer.rsget_response.rssync_info.rsget_sync_status()accessorCloses #188
[AI-assisted - Claude]