From bdfc94b2178688d747b71659022a0508461040f2 Mon Sep 17 00:00:00 2001 From: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co> Date: Sun, 19 Jul 2026 13:51:52 -0700 Subject: [PATCH] fix(mobile): keep startup independent of crash reporting Co-authored-by: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1ft62tztwwm2x9xamk25smmuaj4sfckdkldksruf2x2jwqalffkrq0g7arr <4af4a5896e76d4629bbbb2a90def9d95609c59b6fb6d01f12a32a4e077e94d86@sprout-oss.stage.blox.sqprod.co> --- mobile/lib/main.dart | 21 +++++++++++++++-- mobile/pubspec.yaml | 3 +++ mobile/test/main_test.dart | 47 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 mobile/test/main_test.dart diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 25bfc3e8c..014d7fcd0 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -6,7 +6,7 @@ import 'app.dart'; import 'shared/diagnostics/diagnostics.dart'; import 'shared/theme/theme_provider.dart'; -void main() async { +Future main() async { WidgetsFlutterBinding.ensureInitialized(); // Pre-load preferences so startup can apply saved diagnostics consent and @@ -17,7 +17,7 @@ void main() async { config: const SentryConfig.fromEnvironment(), crashReporter: const SentryCrashReporter(), ); - await diagnosticsController.applyStartupConsent(); + await applyStartupDiagnosticsConsent(diagnosticsController); runApp( ProviderScope( @@ -31,3 +31,20 @@ void main() async { ), ); } + +/// Applies diagnostics consent without allowing optional crash reporting to +/// prevent the app from starting. +@visibleForTesting +Future applyStartupDiagnosticsConsent( + DiagnosticsController diagnosticsController, { + DiagnosticsLog? log, +}) async { + try { + await diagnosticsController.applyStartupConsent(); + } on Object catch (error, stackTrace) { + (log ?? debugPrint)( + 'Diagnostics startup failed; continuing without crash reporting: ' + '$error\n$stackTrace', + ); + } +} diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 3ab2623b5..4d3bc9e4f 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -32,6 +32,9 @@ dependencies: app_badge_plus: ^1.2.10 app_links: ^6.4.0 scrollable_positioned_list: ^0.3.8 + # 9.24.0 still pins jni 0.14.2, so the resolver also selects the + # compatible path_provider_android 2.2.23 instead of the prior jni 1.0.0 + # graph. Keep this exact pin until Sentry publishes a compatible release. sentry_flutter: 9.24.0 dev_dependencies: diff --git a/mobile/test/main_test.dart b/mobile/test/main_test.dart new file mode 100644 index 000000000..7ee5d8199 --- /dev/null +++ b/mobile/test/main_test.dart @@ -0,0 +1,47 @@ +import 'package:buzz/main.dart' as app; +import 'package:buzz/shared/diagnostics/diagnostics.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +void main() { + test('startup continues when crash reporting initialization fails', () async { + SharedPreferences.setMockInitialValues({ + diagnosticsConsentPreferenceKey: true, + }); + final preferences = await SharedPreferences.getInstance(); + final logs = []; + final controller = DiagnosticsController( + preferences: preferences, + config: const SentryConfig( + dsn: 'https://public@example.invalid/1', + release: 'buzz@1.2.3', + dist: '42', + environment: 'production', + ), + crashReporter: _FailingCrashReporter(), + ); + + await expectLater( + app.applyStartupDiagnosticsConsent(controller, log: logs.add), + completes, + ); + + expect( + logs.single, + contains( + 'Diagnostics startup failed; continuing without crash reporting: ' + 'Bad state: init failed', + ), + ); + }); +} + +class _FailingCrashReporter implements CrashReporter { + @override + Future initialize(SentryConfig config) async { + throw StateError('init failed'); + } + + @override + Future close() async {} +}