npx skills add ...
npx skills add getsentry/sentry-for-ai --skill sentry-flutter-sdk
Full Sentry SDK setup for Flutter and Dart. Use when asked to "add Sentry to Flutter", "install sentry_flutter", "setup Sentry in Dart", or configure error monitoring, tracing, profiling, session replay, or logging for Flutter applications. Supports Android, iOS, macOS, Linux, Windows, and Web.
npx skills add getsentry/sentry-for-ai --skill sentry-flutter-sdk
All Skills > SDK Setup > Flutter SDK
Opinionated wizard that scans your Flutter or Dart project and guides you through complete Sentry setup — error monitoring, tracing, session replay, logging, profiling, and ecosystem integrations.
sentry_flutter, sentry_dart, mobile error tracking, or Sentry for FlutterNote: SDK versions and APIs below reflect
sentry_flutter≥9.14.0 (current stable, February 2026). Always verify against docs.sentry.io/platforms/flutter/ before implementing.
Run these commands to understand the project before making any recommendations:
What to determine:
| Question | Impact |
|---|---|
sentry_flutter already in pubspec.yaml? | Skip install, jump to feature config |
Dart SDK >=3.5? | Required for sentry_flutter ≥9.0.0 |
go_router or auto_route present? | Use SentryNavigatorObserver — specific patterns apply |
dio present? | Recommend sentry_dio integration |
sqflite, drift, hive, isar present? | Recommend matching sentry_* DB package |
Has android/ and ios/ directories? | Full mobile feature set available |
Has web/ directory only? | Session Replay and Profiling unavailable |
Has macos/ directory? | Profiling available (alpha) |
| Backend directory detected? | Trigger Phase 4 cross-link |
Present a concrete recommendation based on what you found. Don't ask open-ended questions — lead with a proposal:
Recommended (core coverage — always set up these):
Optional (enhanced observability):
Sentry.logger.* and sentry_logging integrationPlatform limitations — be upfront:
| Feature | Platforms | Notes |
|---|---|---|
| Session Replay | iOS, Android | Not available on macOS, Linux, Windows, Web |
| Profiling | iOS, macOS | Alpha status; not available on Android, Linux, Windows, Web |
| Native crashes | iOS, Android, macOS | NDK/signal handling; Linux/Windows/Web: Dart exceptions only |
| App Start metrics | iOS, Android | Not available on desktop/web |
| Slow/frozen frames | iOS, Android, macOS | Not available on Linux, Windows, Web |
| Crons | N/A | Not available in the Flutter/Dart SDK |
Propose: "For your Flutter app targeting iOS/Android, I recommend Error Monitoring + Tracing + Session Replay. Want me to also add Logging and Profiling (iOS/macOS alpha)?"
| Project type | Recommended setup |
|---|---|
| Any Flutter app | Wizard CLI (handles pubspec, init, symbol upload) |
| Manual preferred | Path B below — pubspec.yaml + main.dart |
| Dart-only (CLI, server) | Path C below — pure sentry package |
You need to run this yourself — the wizard opens a browser for login and requires interactive input that the agent can't handle. Copy-paste into your terminal:
It handles org/project selection, adds
sentry_fluttertopubspec.yaml, updatesmain.dart, configuressentry_dart_pluginfor debug symbol upload, and adds build scripts. Here's what it creates/modifies:
File Action Purpose pubspec.yamlAdds sentry_flutterdependency andsentry:config blockSDK + symbol upload config lib/main.dartWraps main()withSentryFlutter.init()SDK initialization android/app/build.gradleAdds Proguard config reference Android obfuscation support .sentryclircAuth token and org/project config Symbol upload credentials Once it finishes, come back and skip to Verification.
If the user skips the wizard, proceed with Path B (Manual Setup) below.
Step 1 — Install
Or add to pubspec.yaml manually:
Then run:
Step 2 — Initialize Sentry in lib/main.dart
Step 3 — Add Navigation Observer
Add SentryNavigatorObserver to your MaterialApp or CupertinoApp:
For GoRouter:
Step 4 — Configure Debug Symbol Upload
Readable stack traces in Sentry require uploading debug symbols when building with --obfuscate.
Add to pubspec.yaml:
Build and upload:
SentryFlutter.init()TTID (Time to Initial Display) is always enabled. TTFD is opt-in:
Then report when your screen has loaded its data:
Walk through features one at a time. Load the reference file for each, follow its steps, then verify before moving on:
| Feature | Reference | Load when... |
|---|---|---|
| Error Monitoring | ${SKILL_ROOT}/references/error-monitoring.md | Always (baseline) |
| Tracing & Performance | ${SKILL_ROOT}/references/tracing.md | Always — navigation, HTTP, DB spans |
| Session Replay | ${SKILL_ROOT}/references/session-replay.md | iOS/Android user-facing apps |
| Profiling | ${SKILL_ROOT}/references/profiling.md | iOS/macOS performance-sensitive apps |
| Logging | ${SKILL_ROOT}/references/logging.md | Structured logging / log-trace correlation |
| Metrics | ${SKILL_ROOT}/references/metrics.md | Custom business metrics |
| Ecosystem Integrations | ${SKILL_ROOT}/references/ecosystem-integrations.md | HTTP clients, databases, GraphQL, state management |
For each feature: Read ${SKILL_ROOT}/references/<feature>.md, follow steps exactly, verify it works.
SentryFlutter.init() Options| Option | Type | Default | Purpose |
|---|---|---|---|
dsn | string | — | Required. Project DSN. Env: SENTRY_DSN via --dart-define |
environment | string | — | e.g., "production", "staging". Env: SENTRY_ENVIRONMENT |
release | string | Auto on iOS/Android | "packageName@version+build". Env: SENTRY_RELEASE |
dist | string | — | Distribution identifier; max 64 chars. Env: SENTRY_DIST |
sendDefaultPii | bool | false | Include PII: IP address, user labels, widget text in replay |
sampleRate | double | 1.0 | Error event sampling (0.0–1.0) |
maxBreadcrumbs | int | 100 | Max breadcrumbs per event |
attachStacktrace | bool | true | Auto-attach stack traces to messages |
attachScreenshot | bool | false | Capture screenshot on error (mobile/desktop only) |
screenshotQuality | enum | high | Screenshot quality: full, high, medium, low |
attachViewHierarchy | bool | false | Attach JSON widget tree as attachment on error |
debug | bool | true in debug | Verbose SDK output. Never force true in production |
diagnosticLevel | enum | warning | Log verbosity: debug, info, warning, error, fatal |
enabled | bool | true | Disable SDK entirely (e.g., for testing) |
maxCacheItems | int | 30 | Max offline-cached envelopes (not supported on Web) |
sendClientReports | bool | true | Send SDK health reports (dropped events, etc.) |
reportPackages | bool | true | Report pubspec.yaml dependency list |
reportSilentFlutterErrors | bool | false | Capture FlutterErrorDetails.silent errors |
idleTimeout | Duration | 3000ms | Auto-finish idle user interaction transactions |
| Option | Type | Default | Purpose |
|---|---|---|---|
tracesSampleRate | double | — | Transaction sample rate (0–1). Enable by setting >0 |
tracesSampler | function | — | Per-transaction sampling; overrides tracesSampleRate |
tracePropagationTargets | List | — | URLs to attach sentry-trace + baggage headers |
propagateTraceparent | bool | false | Also send W3C traceparent header (SDK ≥9.7.0) |
enableTimeToFullDisplayTracing | bool | false | Opt-in TTFD tracking per screen |
enableAutoPerformanceTracing | bool | true | Auto-enable performance monitoring |
enableUserInteractionTracing | bool | true | Create transactions for tap/click/long-press events |
enableUserInteractionBreadcrumbs | bool | true | Breadcrumbs for every tracked user interaction |
| Option | Type | Default | Purpose |
|---|---|---|---|
profilesSampleRate | double | — | Profiling rate relative to tracesSampleRate. iOS/macOS only |
| Option | Type | Default | Purpose |
|---|---|---|---|
autoInitializeNativeSdk | bool | true | Auto-initialize native Android/iOS SDK layer |
enableNativeCrashHandling | bool | true | Capture native crashes (NDK, signal, Mach exception) |
enableNdkScopeSync | bool | true | Sync Dart scope to Android NDK |
enableScopeSync | bool | true | Sync scope data to native SDKs |
anrEnabled | bool | true | ANR detection (Android) |
anrTimeoutInterval | int | 5000 | ANR timeout in milliseconds (Android) |
enableWatchdogTerminationTracking | bool | true | OOM kill tracking (iOS) |
enableTombstone | bool | false | Android 12+ native crash info via ApplicationExitInfo |
attachThreads | bool | false | Attach all threads on crash (Android) |
captureNativeFailedRequests | bool | — | Native HTTP error capture, independent of Dart client (iOS/macOS, v9.11.0+) |
enableAutoNativeAppStart | bool | true | App start timing instrumentation (iOS/Android) |
enableFramesTracking | bool | true | Slow/frozen frame monitoring (iOS/Android/macOS) |
proguardUuid | string | — | Proguard UUID for Android obfuscation mapping |
| Option | Type | Default | Purpose |
|---|---|---|---|
enableAutoSessionTracking | bool | true | Session tracking for crash-free user/session metrics |
autoSessionTrackingInterval | Duration | 30s | Background inactivity before session ends |
options.replay)| Option | Type | Default | Purpose |
|---|---|---|---|
replay.sessionSampleRate | double | 0.0 | Fraction of all sessions recorded |
replay.onErrorSampleRate | double | 0.0 | Fraction of error sessions recorded |
options.privacy)| Option / Method | Default | Purpose |
|---|---|---|
privacy.maskAllText | true | Mask all text widget content |
privacy.maskAllImages | true | Mask all image widgets |
privacy.maskAssetImages | true | Mask images from root asset bundle |
privacy.mask<T>() | — | Mask a specific widget type and all subclasses |
privacy.unmask<T>() | — | Unmask a specific widget type |
privacy.maskCallback<T>() | — | Custom masking decision per widget instance |
| Option | Type | Default | Purpose |
|---|---|---|---|
captureFailedRequests | bool | true (Flutter) | Auto-capture HTTP errors |
maxRequestBodySize | enum | never | Body capture: never, small, medium, always |
failedRequestStatusCodes | List | [500–599] | Status codes treated as failures |
failedRequestTargets | List | ['.*'] | URL patterns to monitor |
| Option | Type | Purpose |
|---|---|---|
beforeSend | (SentryEvent, Hint) → SentryEvent? | Modify or drop error events. Return null to drop |
beforeSendTransaction | (SentryEvent) → SentryEvent? | Modify or drop transaction events |
beforeBreadcrumb | (Breadcrumb, Hint) → Breadcrumb? | Process breadcrumbs before storage |
beforeSendLog | (SentryLog) → SentryLog? | Filter structured logs before sending |
Pass via --dart-define at build time:
| Variable | Purpose | Notes |
|---|---|---|
SENTRY_DSN | Data Source Name | Falls back from options.dsn |
SENTRY_ENVIRONMENT | Deployment environment | Falls back from options.environment |
SENTRY_RELEASE | Release identifier | Falls back from options.release |
SENTRY_DIST | Build distribution | Falls back from options.dist |
SENTRY_AUTH_TOKEN | Upload debug symbols | Never embed in app — build tool only |
SENTRY_ORG | Organization slug | Used by sentry_dart_plugin |
SENTRY_PROJECT | Project slug | Used by sentry_dart_plugin |
Usage:
Then in code:
Lower sample rates and harden config before shipping:
These are active with no extra config when you call SentryFlutter.init():
| Integration | What it does |
|---|---|
FlutterErrorIntegration | Captures FlutterError.onError framework errors |
RunZonedGuardedIntegration | Catches unhandled Dart exceptions in runZonedGuarded |
NativeAppStartIntegration | App start timing (iOS/Android) |
FramesTrackingIntegration | Slow/frozen frames (iOS/Android/macOS) |
NativeUserInteractionIntegration | User interaction breadcrumbs from native layer |
UserInteractionIntegration | Dart-layer tap/click transactions (requires SentryWidget) |
DeviceContextIntegration | Device model, OS version, screen resolution |
AppContextIntegration | App version, build number, bundle ID |
ConnectivityIntegration | Network connectivity change breadcrumbs |
HttpClientIntegration | Auto-instrument Dart http requests |
SdkIntegration | SDK metadata tagging |
ReleaseIntegration | Auto-set release on iOS/Android from package info |
After setup, test that Sentry is receiving events:
Check the Sentry dashboard:
enableLogs: true⚠️ Platform limitations in debug mode:
- Native crashes, session replay, slow/frozen frames, and app start metrics only fully work in release builds on iOS/Android
- Run
flutter run --releaseor use a real device/emulator to test native features- Debug mode uses the Dart VM with JIT compilation — some native integrations behave differently
After completing Flutter setup, check for a backend missing Sentry coverage:
If a backend exists without Sentry, suggest the matching skill:
| Detected | Suggest skill |
|---|---|
Go backend (go.mod) | sentry-go-sdk |
Python backend (requirements.txt, pyproject.toml) | sentry-python-sdk |
Ruby backend (Gemfile) | sentry-ruby-sdk |
| Node.js backend | sentry-node-sdk |
.NET backend (*.csproj) | sentry-dotnet-sdk |
| React / Next.js web | sentry-react-sdk / sentry-nextjs-sdk |
Distributed tracing — if a backend skill is added, configure tracePropagationTargets in Flutter to propagate trace context to your API:
This links mobile transactions to backend traces in the Sentry waterfall view.
| Issue | Solution |
|---|---|
| Events not appearing in Sentry | Set options.debug = true — SDK logs to Flutter console; verify DSN is correct |
SentryFlutter.init throws | Ensure main() is async and you await SentryFlutter.init(...) |
| Stack traces unreadable in Sentry | Upload debug symbols with sentry_dart_plugin; build with --obfuscate --split-debug-info |
| Stack traces missing on Web | Build with --source-maps and run dart run sentry_dart_plugin to upload |
| Native crashes not captured | Confirm enableNativeCrashHandling: true; test in release mode, not debug |
| Session replay not recording | iOS/Android only; confirm SentryWidget wraps root; check replay.onErrorSampleRate |
| Replay shows blank screens | Confirm SentryWidget(child: MyApp()) is outermost widget; not inside navigator |
| Profiling not working | iOS and macOS only (alpha); confirm tracesSampleRate > 0 is set first |
| Navigation not tracked | Add SentryNavigatorObserver() to navigatorObservers; name all routes |
| GoRouter routes unnamed | Add name: to all GoRoute entries — unnamed routes are tracked as null |
| TTFD never reports | Call SentryFlutter.currentDisplay()?.reportFullyDisplayed() after data loads, or wrap with SentryDisplayWidget |
sentry_dart_plugin auth error | Set SENTRY_AUTH_TOKEN env var instead of hardcoding in pubspec.yaml |
| Android ProGuard mapping missing | Ensure --extra-gen-snapshot-options=--save-obfuscation-map=... flag is set |
| iOS dSYM not uploaded | sentry_dart_plugin handles this; check upload_debug_symbols: true in pubspec.yaml sentry: block |
pub get fails: Dart SDK too old | sentry_flutter ≥9.0.0 requires Dart ≥3.5.0; run flutter upgrade |
| Hot restart crashes on Android debug | Known issue (fixed in SDK ≥9.9.0); upgrade if on older version |
| ANR detection too aggressive | Increase anrTimeoutInterval (default: 5000ms) |
| Too many transactions in dashboard | Lower tracesSampleRate to 0.1 or use tracesSampler to drop health checks |
beforeSend not firing for native crashes | Expected — beforeSend intercepts only Dart-layer events; native crashes bypass it |
| Crons not available | The Flutter/Dart SDK does not support Sentry Crons; use a server-side SDK instead |
SentryWidget warning in tests | Wrap test widget with SentryFlutter.init() in setUpAll, or use enabled: false |
| Firebase Remote Config: Linux/Windows | sentry_firebase_remote_config not supported on Linux/Windows (Firebase limitation) |
| Isar tracing on Web | sentry_isar does NOT support Web (Isar does not support Web) |