From afc2f7ba3d149af3ed906c81ba4a271181fd8f99 Mon Sep 17 00:00:00 2001 From: Strycher Date: Sat, 20 Jun 2026 14:09:27 -0400 Subject: [PATCH] fix(#26): surface swallowed errors in connector fire-and-forget paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrap unhandled async work in meshcore_connector.dart so failures log instead of vanishing (SAFELANE ยง6 Error Visibility): - A: fire-and-forget message-handler IIFEs (translation + notification) in _handleIncomingMessage / _handleIncomingChannelMessage / _handleLogRxData / _maybeNotifyChannelMessage now .catchError -> log. - B: _persistContacts / _persistDiscoveredContacts try/catch -> log. - C: two unawaited _channelStore.saveChannels writes .catchError -> log. Bounded A/B/C pass; D (store debounce writers) + E (misc connector unawaited ops) deferred per this issue's opportunistic strategy. Co-Authored-By: Claude Opus 4.8 --- lib/connector/meshcore_connector.dart | 66 +++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 60ebe95..478fa37 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -796,9 +796,14 @@ class MeshCoreConnector extends ChangeNotifier { tag: 'Unread', ); unawaited( - _channelStore.saveChannels( - _channels.isNotEmpty ? _channels : _cachedChannels, - ), + _channelStore + .saveChannels(_channels.isNotEmpty ? _channels : _cachedChannels) + .catchError((Object e) { + _appDebugLogService?.error( + 'Failed to persist channels (markChannelRead): $e', + tag: 'ChannelStore', + ); + }), ); _notificationService.clearChannelNotification( channelIndex, @@ -3679,7 +3684,14 @@ class MeshCoreConnector extends ChangeNotifier { // Cache channels for offline use _cachedChannels = List.from(_channels); - unawaited(_channelStore.saveChannels(_channels)); + unawaited( + _channelStore.saveChannels(_channels).catchError((Object e) { + _appDebugLogService?.error( + 'Failed to persist channels (channel sync): $e', + tag: 'ChannelStore', + ); + }), + ); _recalculateCachedChannelsUnreadTotal(); // Apply ordering and notify UI @@ -4477,11 +4489,25 @@ class MeshCoreConnector extends ChangeNotifier { } Future _persistContacts() async { - await _contactStore.saveContacts(_contacts); + try { + await _contactStore.saveContacts(_contacts); + } catch (e) { + _appDebugLogService?.error( + 'Failed to persist contacts: $e', + tag: 'ContactStore', + ); + } } Future _persistDiscoveredContacts() async { - await _discoveryContactStore.saveContacts(_discoveredContacts); + try { + await _discoveryContactStore.saveContacts(_discoveredContacts); + } catch (e) { + _appDebugLogService?.error( + 'Failed to persist discovered contacts: $e', + tag: 'ContactStore', + ); + } } int _latestContactLastmod() { @@ -4695,7 +4721,12 @@ class MeshCoreConnector extends ChangeNotifier { badgeCount: getTotalUnreadCount(), ); } - }()); + }().catchError((Object e) { + _appDebugLogService?.error( + 'Failed to translate/notify incoming message: $e', + tag: 'Notification', + ); + })); } } _handleQueuedMessageReceived(); @@ -4998,7 +5029,12 @@ class MeshCoreConnector extends ChangeNotifier { channelIndex: message.channelIndex, badgeCount: getTotalUnreadCount(), ); - }()); + }().catchError((Object e) { + _appDebugLogService?.error( + 'Failed to notify channel message: $e', + tag: 'Notification', + ); + })); } void _handleIncomingChannelMessage(Uint8List frame) async { @@ -5035,7 +5071,12 @@ class MeshCoreConnector extends ChangeNotifier { msg, ); _maybeNotifyChannelMessage(msg, translationResult: translationResult); - }()); + }().catchError((Object e) { + _appDebugLogService?.error( + 'Failed to translate/notify channel message: $e', + tag: 'Notification', + ); + })); } _handleQueuedMessageReceived(); } else if (_isSyncingQueuedMessages) { @@ -5128,7 +5169,12 @@ class MeshCoreConnector extends ChangeNotifier { channelName: label, translationResult: translationResult, ); - }()); + }().catchError((Object e) { + _appDebugLogService?.error( + 'Failed to translate/notify channel message (log): $e', + tag: 'Notification', + ); + })); } return; } catch (e) {