Summary When using Appwrite Cloud with the Flutter SDK (latest appwrite release: 21.4.0), Realtime crashes with:
#0 new RealtimeMessage.fromMap (package:appwrite/src/realtime_message.dart:57:47)```
The crash occurs as soon as a real Realtime event (`.create`, `.update`, `.delete`) is received. Heartbeat messages work fine.
This happens before the event reaches the userβs sub.stream.listen(...) callback.
**Environment**
- Appwrite Cloud
- Endpoint: https://cloud.appwrite.io/v1
- Flutter SDK: appwrite: 21.4.0
- Platform: Android (Flutter)
**Root Cause**
Inside the Flutter SDK, RealtimeMessage.fromMap assumes that:
events: List<String> channels: List<String>
However, under certain conditions, the Realtime WebSocket payload delivers `events` and/or `channels` as a Map instead of a `List`.
Because the SDK strictly casts:
(map['events'] as List)
it throws:
type '_Map<String, dynamic>' is not a subtype of type 'Iterable<dynamic>'
This indicates the parser is not tolerant to slight payload structure variations.
**Reproduction**
Minimal example:
final sub = realtime.subscribe([ 'databases.{dbId}.collections.{collectionId}.documents' ]);
sub.stream.listen((event) { print(event); });
As soon as a document `.create` or `.update` event is triggered,
the SDK crashes in `RealtimeMessage.fromMap`.
Proposed Fix (Robust Parsing)
Making RealtimeMessage.fromMap tolerant to both List and Map resolves the issue completely.
Example patch:
static List<String> _coerceStringList(dynamic v) {
if (v == null) return const [];
if (v is List) return v.map((e) => e.toString()).toList();
if (v is Map) return v.values.map((e) => e.toString()).toList();
return [v.toString()];
}
factory RealtimeMessage.fromMap(Map<String, dynamic> map) {
final dynamic data = map['data'];
final Map<String, dynamic> m =
data is Map<String, dynamic> ? data : map;
return RealtimeMessage(
events: _coerceStringList(m['events']),
payload: Map<String, dynamic>.from(m['payload'] ?? const {}),
channels: _coerceStringList(m['channels']),
timestamp: (m['timestamp'] ?? '').toString(),
);
}
After applying this change locally, Realtime works reliably without crashes.
Why This Matters
- The crash occurs before user code can handle errors.
- It makes Realtime unusable in production Flutter apps.
- The fix is small and backward-compatible.
- Making parsing tolerant prevents similar crashes in the future if payload shape slightly changes.
Recommended threads
- Error code 526
Site down. Invalid SSL certificate Error code 526 Could anyone take a look please, thank you. Please DM me for detail.
- Appwrite console Oauth providers issue
Hi, I think I found an issue with the oauth providers tab on the console. If I set up a provider and I turn it on, after about a day it automatically disables i...
- Realtime Connection Error After Updating...
I get the following error message now when the realtime subscription picks up a new message. There's more to the error but it makes the discord message too long...