[{"data":1,"prerenderedAt":23},["ShallowReactive",2],{"articolo-gestione-degli-errori-in-flutter-crash-reporting-e-strategie-con-result-e-sentry":3,"comments-article-gestione-degli-errori-in-flutter-crash-reporting-e-strategie-con-result-e-sentry":22},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},37,"Gestione degli errori in Flutter: crash reporting e strategie con Result e Sentry","gestione-degli-errori-in-flutter-crash-reporting-e-strategie-con-result-e-sentry","Impara a gestire gli errori in modo robusto in Flutter: dal pattern Result per gli errori prevedibili al crash reporting in produzione con Sentry, passando per gli error handler globali.","## Perché la gestione degli errori merita una strategia\n\nIn ogni app reale gli errori sono inevitabili: chiamate di rete che falliscono, parsing JSON malformato, eccezioni inattese nel codice. La differenza tra un'app amatoriale e una professionale sta nel modo in cui questi errori vengono catturati, comunicati all'utente e monitorati in produzione.\n\nIn questo articolo vedremo tre livelli di gestione:\n\n1. Gli **error handler globali** di Flutter per intercettare tutto.\n2. Il **pattern Result** per rappresentare in modo esplicito gli errori prevedibili.\n3. Il **crash reporting** in produzione con Sentry.\n\n## Gli error handler globali\n\nFlutter offre diversi punti di aggancio per catturare gli errori non gestiti. È buona norma configurarli nel `main`.\n\n```dart\nvoid main() {\n  runZonedGuarded(() {\n    \u002F\u002F Errori del framework (build, layout, ecc.)\n    FlutterError.onError = (FlutterErrorDetails details) {\n      FlutterError.presentError(details);\n      logError(details.exception, details.stack);\n    };\n\n    \u002F\u002F Errori a basso livello della piattaforma\n    PlatformDispatcher.instance.onError = (error, stack) {\n      logError(error, stack);\n      return true;\n    };\n\n    runApp(const MyApp());\n  }, (error, stack) {\n    \u002F\u002F Errori asincroni non catturati\n    logError(error, stack);\n  });\n}\n```\n\nQuesti tre canali insieme coprono la stragrande maggioranza degli errori: quelli del framework, quelli nativi e quelli asincroni fuori dalla zone.\n\n## Il pattern Result per errori prevedibili\n\nLanciare eccezioni per errori attesi (come una rete offline) rende il flusso difficile da seguire. Il pattern **Result** rende esplicito, nel tipo di ritorno, che un'operazione può fallire.\n\nDa Dart 3 possiamo usare i `sealed class` e il pattern matching per un'implementazione elegante.\n\n```dart\nsealed class Result\u003CT> {\n  const Result();\n}\n\nfinal class Success\u003CT> extends Result\u003CT> {\n  final T value;\n  const Success(this.value);\n}\n\nfinal class Failure\u003CT> extends Result\u003CT> {\n  final Object error;\n  final StackTrace? stackTrace;\n  const Failure(this.error, [this.stackTrace]);\n}\n```\n\nUn repository può quindi restituire un `Result` invece di lanciare eccezioni:\n\n```dart\nFuture\u003CResult\u003CUser>> fetchUser(String id) async {\n  try {\n    final response = await dio.get('\u002Fusers\u002F$id');\n    return Success(User.fromJson(response.data));\n  } catch (e, stack) {\n    return Failure(e, stack);\n  }\n}\n```\n\nNel layer di presentazione il consumo è chiaro e obbliga il compilatore a gestire entrambi i casi:\n\n```dart\nfinal result = await repository.fetchUser('42');\n\nswitch (result) {\n  case Success(:final value):\n    emit(UserLoaded(value));\n  case Failure(:final error):\n    emit(UserError(_mapError(error)));\n}\n```\n\n### Convertire gli errori in messaggi utente\n\nGli utenti non devono mai vedere un'eccezione grezza. Mappa gli errori tecnici in messaggi comprensibili:\n\n```dart\nString _mapError(Object error) {\n  return switch (error) {\n    DioException(type: DioExceptionType.connectionError) =>\n      'Nessuna connessione a Internet.',\n    DioException(response: final r?) when r.statusCode == 404 =>\n      'Risorsa non trovata.',\n    _ => 'Si è verificato un errore imprevisto.',\n  };\n}\n```\n\n## Crash reporting in produzione con Sentry\n\nGli error handler intercettano gli errori localmente, ma in produzione hai bisogno di sapere cosa succede sui dispositivi degli utenti. **Sentry** è tra le soluzioni più usate.\n\nAggiungi la dipendenza:\n\n```yaml\ndependencies:\n  sentry_flutter: ^8.0.0\n```\n\nSentry semplifica l'inizializzazione gestendo internamente gli handler globali:\n\n```dart\nFuture\u003Cvoid> main() async {\n  await SentryFlutter.init(\n    (options) {\n      options.dsn = 'https:\u002F\u002Fesempio@sentry.io\u002F123';\n      options.tracesSampleRate = 0.2; \u002F\u002F performance monitoring\n      options.environment = kReleaseMode ? 'production' : 'development';\n    },\n    appRunner: () => runApp(const MyApp()),\n  );\n}\n```\n\n### Inviare errori catturati manualmente\n\nPer gli errori che gestisci con il pattern Result puoi comunque loggarli su Sentry senza interrompere l'app:\n\n```dart\nvoid logError(Object error, StackTrace? stack) {\n  Sentry.captureException(error, stackTrace: stack);\n}\n```\n\n### Aggiungere contesto\n\nUn crash isolato dice poco. Aggiungi breadcrumb e informazioni sull'utente per una diagnosi più rapida:\n\n```dart\nSentry.configureScope((scope) {\n  scope.setUser(SentryUser(id: user.id));\n  scope.setTag('feature', 'checkout');\n});\n\nSentry.addBreadcrumb(\n  Breadcrumb(message: 'Utente ha aperto il carrello'),\n);\n```\n\n## Best practice riepilogative\n\n- **Non ignorare mai gli errori** con un `catch` vuoto: almeno loggali.\n- Usa il **pattern Result** per gli errori attesi e le **eccezioni** solo per condizioni davvero inaspettate.\n- Configura **tutti e tre** gli handler globali (`FlutterError.onError`, `PlatformDispatcher.onError`, `runZonedGuarded`).\n- Attiva il crash reporting **solo in release** o distingui gli ambienti con `environment`.\n- **Non loggare dati sensibili**: filtra le informazioni prima di inviarle a servizi esterni.\n- Mostra all'utente messaggi chiari, non stack trace.\n\n## Conclusione\n\nUna strategia di gestione degli errori a più livelli rende la tua app Flutter più robusta e manutenibile. Il pattern Result porta chiarezza nel codice, gli handler globali fanno da rete di sicurezza e strumenti come Sentry ti danno visibilità su ciò che accade dopo il rilascio. Investire in questa infrastruttura fin dall'inizio ripaga in ogni fase del ciclo di vita del prodotto.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fdb2bb312-683c-44b7-9bda-3ec83af4f5e0.jpg",null,"published","2026-07-11T04:00:40+00:00","Gestione errori in Flutter: pattern Result e Sentry","Guida alla gestione degli errori in Flutter: handler globali, pattern Result con Dart 3 e crash reporting in produzione con Sentry. Best practice ed esempi.",{"id":16,"name":17,"slug":18},3,"Best practice","best-practice",{"id":20,"name":21},1,"Flutter Bot",[],1785219602024]