fix: don't drop a message when a payload field is null - #3131
Open
blue-archon wants to merge 1 commit into
Open
blue-archon wants to merge 1 commit into
blue-archon wants to merge 1 commit into
Conversation
Member
|
im still not sure about this deepNormalize function... you've had it on a couple of PRs already, and I feel like it's compensation for something that should be resolved somewhere else at the root. Maybe casting it properly from the start rather than having to normalize it like we are. Maybe I'm wrong, but something feels off here |
blue-archon
force-pushed
the
fix/null-field-message-crash
branch
from
July 25, 2026 20:11
b9c61c3 to
4091815
Compare
Contributor
Author
|
You're right, that's the cleaner fix. The real bug was the cast target: |
blue-archon
added a commit
to blue-archon/bluebubbles-app
that referenced
this pull request
Jul 26, 2026
…deepNormalize Per zlshames's review on BlueBubblesApp#3131: the root fix is to cast decoded payloads to Map<String, dynamic> (what fromMap already expects, and which permits null values) instead of the non-nullable Map<String, Object>. Replace asStringDynamicMapRequired with .cast<String, dynamic>() at the parse sites, restore the plain jsonDecode/cast at the method-channel boundary, and delete deep_map_normalize.dart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
blue-archon
added a commit
to blue-archon/bluebubbles-app
that referenced
this pull request
Aug 3, 2026
…deepNormalize Per zlshames's review on BlueBubblesApp#3131: the root fix is to cast decoded payloads to Map<String, dynamic> (what fromMap already expects, and which permits null values) instead of the non-nullable Map<String, Object>. Replace asStringDynamicMapRequired with .cast<String, dynamic>() at the parse sites, restore the plain jsonDecode/cast at the method-channel boundary, and delete deep_map_normalize.dart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
blue-archon
added a commit
to blue-archon/bluebubbles-app
that referenced
this pull request
Aug 4, 2026
…deepNormalize Per zlshames's review on BlueBubblesApp#3131: the root fix is to cast decoded payloads to Map<String, dynamic> (what fromMap already expects, and which permits null values) instead of the non-nullable Map<String, Object>. Replace asStringDynamicMapRequired with .cast<String, dynamic>() at the parse sites, restore the plain jsonDecode/cast at the method-channel boundary, and delete deep_map_normalize.dart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
blue-archon
added a commit
to blue-archon/bluebubbles-app
that referenced
this pull request
Aug 12, 2026
…deepNormalize Per zlshames's review on BlueBubblesApp#3131: the root fix is to cast decoded payloads to Map<String, dynamic> (what fromMap already expects, and which permits null values) instead of the non-nullable Map<String, Object>. Replace asStringDynamicMapRequired with .cast<String, dynamic>() at the parse sites, restore the plain jsonDecode/cast at the method-channel boundary, and delete deep_map_normalize.dart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
blue-archon
force-pushed
the
fix/null-field-message-crash
branch
from
August 12, 2026 19:35
4091815 to
fefca59
Compare
blue-archon
added a commit
to blue-archon/bluebubbles-app
that referenced
this pull request
Aug 14, 2026
…deepNormalize Per zlshames's review on BlueBubblesApp#3131: the root fix is to cast decoded payloads to Map<String, dynamic> (what fromMap already expects, and which permits null values) instead of the non-nullable Map<String, Object>. Replace asStringDynamicMapRequired with .cast<String, dynamic>() at the parse sites, restore the plain jsonDecode/cast at the method-channel boundary, and delete deep_map_normalize.dart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Incoming chat/message/attachment parsing cast the decoded payload with .cast<String, Object>(). That builds a CastMap that re-casts every value to the non-nullable Object, so a genuinely null field throws a cast error and the whole parse aborts, dropping that chat/message/attachment. It fires on live socket and method-channel (FCM/UnifiedPush) new and updated-message events. The maps are handed to fromMap, which already takes Map<String, dynamic>, so the cast target should have been dynamic all along. Cast to .cast<String, dynamic>() instead, which permits the null. Also default a null attributedBody string to empty so it does not throw at construction once the cast no longer throws first.
blue-archon
added a commit
to blue-archon/bluebubbles-app
that referenced
this pull request
Sep 29, 2026
…deepNormalize Per zlshames's review on BlueBubblesApp#3131: the root fix is to cast decoded payloads to Map<String, dynamic> (what fromMap already expects, and which permits null values) instead of the non-nullable Map<String, Object>. Replace asStringDynamicMapRequired with .cast<String, dynamic>() at the parse sites, restore the plain jsonDecode/cast at the method-channel boundary, and delete deep_map_normalize.dart. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
blue-archon
force-pushed
the
fix/null-field-message-crash
branch
from
September 29, 2026 14:09
fefca59 to
8ceff76
Compare
This branch has not been deployed
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
Incoming chat/message/attachment parsing casts the decoded payload with
.cast<String, Object>(). The resultingCastMapre-casts every value to the non-nullableObjectand throws aNull is not a subtype of Objectcast error the first time any field is genuinely null. That aborts the whole parse and drops the chat/message/attachment for that event.It fires on live
new-message/updated-messageevents from both the socket (action_handler) and the method channel (FCM/UnifiedPush). Incremental sync backfills the item later, so it looks intermittent, but the real-time event is lost in the meantime. Seen on both Android and desktop during normal use, for example a null run inside anattributedBody.Fix
Add a guarded
deepNormalizeJson(lib/utils/deep_map_normalize.dart) that rebuilds maps and lists with null-tolerant reads and returns scalars (including numeric-looking strings like"1234") untouched. Route every parse site throughasStringDynamicMapRequiredinstead of the raw cast: the method-channel entrypoints, the socketaction_handler, andChat/Message/AttributedBodyfromMap.No behavior change on well-formed payloads; a null field now parses instead of throwing.