---
title: "Migrate from 9.x to 10.x"
description: "Learn how to migrate your Flutter application from Sentry SDK 9.x to 10.x."
url: https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10/
---

# Migrate from 9.x to 10.x for Flutter

Version 10 raises the minimum supported platform versions, removes deprecated APIs, and changes several telemetry defaults. The biggest changes are:

* **Platform and build requirements:** Dart 3.12 and Flutter 3.44 are the new minimums, along with Android API 26, iOS 15, and macOS 12. Apple builds use Swift Package Manager instead of CocoaPods, and Android builds use Flutter's Kotlin support.
* **API removals:** Profiling and deprecated APIs, including `copyWith` and `SentryFeedbackWidget`, are removed. Logs and metrics no longer need enable flags.
* **Telemetry behavior:** The logging integration forwards Sentry logs by default, native failed-request capture becomes opt-in, and throwing filtering callbacks drop the affected telemetry.
* **Tracing:** Stream mode is now the default. Migrate custom transaction instrumentation, filtering callbacks, and samplers, or explicitly select `SentryTraceLifecycle.static` to retain transaction mode.
* **App-start tracing:** App start is a standalone `app.start` trace with its own sampling decision and a revised frame-span breakdown. Review custom sampling rules, dashboards, and alerts.
* **Desktop crash reporting:** Windows and Linux default to Breakpad, with native crash reports uploaded after an application restart. A build-time override retains Crashpad.
* **Flutter web:** The bundled JavaScript SDK moves to v11, and browser sessions report unhandled errors as `unhandled` rather than `crashed`. Flutter's `sendDefaultPii` option remains supported.

The guide includes core Dart SDK changes that affect Flutter applications.

##### Prefer a checklist?

The [Interactive v10 Migration Guide](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10/interactive.md) lets you check off completed migration steps.

## [Minimum Supported Versions](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#minimum-supported-versions)

Update your local development environment and CI before upgrading:

| Dependency              | v9 Minimum | v10 Minimum |
| ----------------------- | ---------- | ----------- |
| Dart                    | `3.5.0`    | `3.12.0`    |
| Flutter                 | `3.24.0`   | `3.44.0`    |
| Android API (`minSdk`)  | `21`       | `26`        |
| iOS deployment target   | `12.0`     | `15.0`      |
| macOS deployment target | `10.14`    | `12.0`      |

## [Update Sentry Packages](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#update-sentry-packages)

Update any directly declared Sentry integration packages, such as `sentry_dio` or `sentry_logging`, to the matching v10 release as well. Update `sentry_flutter` to v10:

```yaml
dependencies:
  sentry_flutter: ^10.0.0
```

The integration dependency constraints also change:

| Package          | Required Dependency                                     |
| ---------------- | ------------------------------------------------------- |
| `sentry_flutter` | `jni >=1.0.0 <1.1.0` (previously `0.14.2`)              |
| `sentry_dio`     | `dio ^5.8.0` (previously `^5.2.0`)                      |
| `sentry_link`    | `gql_link >=0.5.1 <2.0.0` (previously `>=0.5.0 <2.0.0`) |

Update conflicting direct dependencies or dependency overrides before running `flutter pub get`.

## [Android Builds Use Flutter's Kotlin Support](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#android-builds-use-flutters-kotlin-support)

The Sentry Flutter plugin no longer applies or bundles its own Kotlin Gradle Plugin. It relies on Flutter 3.44's Kotlin support. If you customize Android build configuration, update it for Flutter 3.44 rather than relying on Sentry to supply Kotlin. This change does not require upgrading your app to AGP 9.

## [Apple Builds Use Swift Package Manager](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#apple-builds-use-swift-package-manager)

The Sentry Flutter plugin no longer supports CocoaPods. On iOS and macOS, it uses Swift Package Manager to install the native Sentry Cocoa SDK, which has been upgraded to v9. If you initialize Sentry separately in native code or call its Swift/Objective-C APIs directly, also review the [Sentry Cocoa v8-to-v9 migration guide](https://docs.sentry.io/platforms/apple/migration/v8-to-v9.md).

Flutter 3.44 enables Swift Package Manager by default and migrates your project when you run the app. If you previously disabled it, re-enable it and remove any project-level `enable-swift-package-manager: false` setting:

```bash
flutter config --enable-swift-package-manager
flutter pub get
```

Set the iOS and macOS deployment targets in Xcode to the minimum versions listed in [Minimum Supported Versions](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#minimum-supported-versions). For custom targets, flavors, or projects that don't migrate automatically, follow [Flutter's Swift Package Manager migration instructions](https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers/).

Other Flutter plugins may still require CocoaPods. Only remove your application's CocoaPods integration once all of its dependencies support Swift Package Manager.

## [Logs and Metrics Are Always Enabled](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#logs-and-metrics-are-always-enabled)

Remove assignments to `options.enableLogs` and `options.enableMetrics`. These options no longer exist. Calls to `Sentry.logger` and `Sentry.metrics` send telemetry without an enable flag. To filter logs or metrics, return `null` from `beforeSendLog` or `beforeSendMetric`.

If you use `sentry_logging`, adding `LoggingIntegration` now also forwards records as Sentry logs, with a default minimum level of `Level.INFO`. If you previously disabled logs and want to keep only breadcrumbs and error events, set `minSentryLogLevel` to `Level.OFF`:

```dart
import 'package:logging/logging.dart';
import 'package:sentry_logging/sentry_logging.dart';

// Inside your SentryFlutter.init options callback:
options.addIntegration(LoggingIntegration(minSentryLogLevel: Level.OFF));
```

The `Sentry.logger` and `Sentry.logger.fmt` methods now return `void`. Remove `await` from log calls. Update custom implementations of `SentryLogger` and `SentryLoggerFormatter` to match these return types. Custom `Hub.captureLog` overrides now return `Future<void>` instead of `FutureOr<void>`.

Replace `SentryLogAttribute` with `SentryAttribute`, using the same typed factories such as `SentryAttribute.string(...)`. If you construct `SentryLog` directly, its `traceId` is now a required, non-nullable `SentryId`. Prefer `Sentry.logger` for application logging so the SDK supplies trace context.

## [Telemetry Callbacks Receive a Hint](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#telemetry-callbacks-receive-a-hint)

Add a second `Hint` parameter to `beforeSendLog`, `beforeSendMetric`, and `beforeSendSpan`, even if you don't use it:

```dart
options.beforeSendLog = (log, hint) {
  return log;
};

options.beforeSendMetric = (metric, hint) {
  return metric;
};

options.beforeSendSpan = (span, hint) {
  span.removeAttribute('private.attribute');
};
```

`beforeSendSpan` modifies the span in place. It cannot drop spans by returning `null`; use `options.ignoreSpans` to filter spans in stream mode.

## [Stream Mode Is the Default](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#stream-mode-is-the-default)

In v10, `SentryTraceLifecycle.stream` is the default. The SDK sends spans in batches as they finish instead of waiting for a transaction to end. Tracing still requires `tracesSampleRate` or `tracesSampler` to be configured.

Automatic instrumentation uses the streaming span APIs. If you use custom instrumentation, migrate `Sentry.startTransaction` and `ISentrySpan.startChild` to the streaming span APIs. Transaction APIs are ignored in stream mode. Move `beforeSendTransaction` and `ignoreTransactions` logic to `beforeSendSpan` and `ignoreSpans`, and update custom samplers to read `samplingContext.spanContext`.

Follow the [stream mode migration guide](https://docs.sentry.io/platforms/dart/guides/flutter/tracing/streamed-spans/migration-guide.md) and use the two-parameter `beforeSendSpan` signature in [Telemetry Callbacks Receive a Hint](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#telemetry-callbacks-receive-a-hint).

To retain transaction mode while migrating, explicitly set `options.traceLifecycle = SentryTraceLifecycle.static` during SDK initialization. Removing this option uses stream mode in v10.

## [App Start Is a Standalone Trace](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#app-start-is-a-standalone-trace)

On Android and iOS, app start is now reported as its own `app.start` root when tracing is enabled. It is no longer attached to the initial `ui.load` transaction and has its own sampling decision.

Remove `options.enableStandaloneAppStartTracing` assignments. The standalone path is now the default, and the option has been removed. Update custom sampling rules, dashboards, and alerts that assume app start belongs to the first navigation transaction. A sampler that only accepts `ui.load` roots may exclude app start.

If startup work continues past the first frame, call `SentryFlutter.extendAppStart()` before the first frame renders and `await SentryFlutter.finishExtendedAppStart()` when that work finishes. An extension that reaches the 30-second app-start deadline is dropped, and the reported duration falls back to the first frame.

The app-start breakdown also changes in v10. Update queries, dashboards, and `beforeSendSpan` callbacks that match `app.start.plugin_registration`, `app.start.sentry_setup`, or `app.start.first_frame_render`. These operations are no longer emitted. The SDK records measured startup work using:

| Operation                          | Measured Work                                 |
| ---------------------------------- | --------------------------------------------- |
| `app.start.root_widget_attachment` | Attachment of the root widget                 |
| `app.start.frame_build`            | Flutter framework frame builds during startup |
| `app.start.frame_raster`           | Rasterization of the first frame              |

These spans are not one-to-one replacements for the previous broad intervals. Frame-build spans include `flutter.frame.warm_up` and `flutter.frame.deferred` attributes. A frame-build span does not by itself mean that the frame was submitted to the engine or displayed.

Startup frame builds that begin at or after the first frame's rasterization starts are also excluded.

## [Native Failed Requests Are Opt-In](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#native-failed-requests-are-opt-in)

On iOS and macOS, `captureNativeFailedRequests` now defaults to `false` and no longer accepts `null`. It no longer falls back to `captureFailedRequests`.

To continue capturing failed HTTP requests made by the native SDK's network instrumentation, opt in explicitly:

```dart
options.captureNativeFailedRequests = true;
```

Dart-side failed request capture through `SentryHttpClient` and `sentry_dio` is still controlled independently by `captureFailedRequests`, which defaults to `true`.

## [Profiling and Deprecated APIs Are Removed](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#profiling-and-deprecated-apis-are-removed)

Remove `options.profilesSampleRate`. The Flutter SDK no longer captures profiles, and there is no replacement profiling option in v10.

Update code that uses the following APIs:

| Removed or Internal API                                                                                                           | Migration                                                                                                                                                               |
| --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SentryFeedbackWidget`                                                                                                            | Use `SentryFeedbackForm`.                                                                                                                                               |
| Deprecated `copyWith(...)` methods on SDK data classes                                                                            | Assign mutable fields directly.                                                                                                                                         |
| Deprecated protocol `clone()` methods                                                                                             | Stop calling them; remaining SDK clone helpers are internal. Construct a new object explicitly if you need an independent copy.                                         |
| `PerformanceCollector`, `PerformanceContinuousCollector`, `options.performanceCollectors`, `options.addPerformanceCollector(...)` | Remove custom collector registration. These deprecated APIs have been removed.                                                                                          |
| `BindingWrapper`, `options.bindingUtils`                                                                                          | Remove custom binding-wrapper overrides. `SentryWidgetsFlutterBinding` remains public.                                                                                  |
| `options.log`, `SdkLogCallback`                                                                                                   | Remove usage of these diagnostic logging APIs. Use `options.debug` and `options.diagnosticLevel` to configure SDK diagnostics, or `Sentry.logger` for application logs. |

The `SentryEventLike<T>` mixin has also been removed with `copyWith`. Use `SentryEvent` as the common type for events and transactions (`SentryTransaction` extends `SentryEvent`).

`Sentry.clone()`, `Hub.clone()`, and `Scope.clone()` are now internal APIs. Remove direct calls to them. For capture-specific context, use the capture method's `withScope` callback.

For example, mutate events in `beforeSend` instead of using `copyWith`:

```dart
options.beforeSend = (event, hint) {
  event.release = 'my-release';
  return event;
};
```

## [Feature Flags Use the Current Scope](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#feature-flags-use-the-current-scope)

Feature flag evaluations now belong to the current hub and scope, rather than `FeatureFlagsIntegration`. If you accessed that integration directly, replace those calls with `await Sentry.addFeatureFlag('flag-name', true)`.

Existing calls to `Sentry.addFeatureFlag` continue to work. Custom `Hub` implementations must implement `addFeatureFlag(String flag, bool result)`.

## [Span Attribute Names Have Changed](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#span-attribute-names-have-changed)

Update queries, dashboards, alerts, and callbacks that read the old attribute keys:

| Previous Attribute             | v10 Attribute             | Affected Instrumentation       |
| ------------------------------ | ------------------------- | ------------------------------ |
| `db.system`                    | `db.system.name`          | Database integrations          |
| `db.name`                      | `db.namespace`            | Drift, Hive, Isar, and sqflite |
| `db.operation`                 | `db.operation.name`       | Supabase                       |
| `db.table`                     | `db.collection.name`      | Supabase                       |
| `db.collection`                | `db.collection.name`      | Isar                           |
| `url`                          | `url.full`                | HTTP spans                     |
| `http.response_content_length` | `http.response.body.size` | HTTP spans                     |
| `app_start_type`               | `app.vitals.start.type`   | App start                      |

Drift's database system value changes from `db.sqlite` to `sqlite`. Supabase replaces the raw filter list under `db.query` and the SQL under `db.sql.query` with a parameterized SQL statement under `db.query.text`, and adds `db.query.summary`. The SQL statement uses placeholders for values and is emitted regardless of `sendDefaultPii`.

The `sentry_file` integration no longer emits `file.async`. `SentrySpanData` has been removed. If you referenced this internal class, use the attribute strings listed above in application code. `SemanticAttributesConstants` and `ProposedSemanticAttributes` are also internal APIs.

For custom code that used internal constants, the old `appApp*`, `osBuild`, `deviceConnectionType`, `deviceLocale`, and `deviceTimezone` constants have been removed. Use the corresponding attribute strings: `app.build`, `app.identifier`, `app.name`, `app.start_time`, `app.version`, `os.build_id`, `network.connection.type`, `culture.locale`, and `culture.timezone`. The `appVitalsStartValue` constant moves to `ProposedSemanticAttributes`; its wire key remains `app.vitals.start.value`.

Database breadcrumb data also uses `db.system.name` and `db.namespace` instead of `db.system` and `db.name` in Hive, Isar, and sqflite. Update `beforeBreadcrumb` callbacks that read these fields.

## [Throwing Callbacks Drop Telemetry](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#throwing-callbacks-drop-telemetry)

In v10, an exception in an event processor or a filtering callback drops the affected telemetry item instead of sending the item through unchanged.

This applies to event processors, `beforeSend`, `beforeSendTransaction`, `beforeSendFeedback`, `beforeBreadcrumb`, `beforeSendLog`, and `beforeSendMetric`. Review callbacks that can throw, especially custom filtering and scrubbing logic. Handle expected failures inside the callback and return the intended item or `null` explicitly.

In transaction mode, a throwing `tracesSampler` uses the inherited sampling decision when available, then falls back to `tracesSampleRate`. In stream mode, it falls back to `tracesSampleRate`. Do not rely on throwing an exception to reject a trace; return `0.0` to reject it explicitly.

## [Error Processing and Release Health](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#error-processing-and-release-health)

Error sampling through `sampleRate` now happens after event processors and `beforeSend`. These callbacks run even for events that are subsequently sampled out, so review callbacks that perform expensive work or have side effects. An event dropped by `beforeSend` is reported as a `before_send` discard rather than a `sample_rate` discard.

On Android, iOS, and macOS, unhandled Flutter errors now mark sessions as unhandled rather than crashed. Unhandled errors dropped by `sampleRate` also affect release health. Review release-health comparisons across the upgrade because session classification and sampling behavior have changed.

For the web session-status change, see [Flutter Web Uses JavaScript SDK v11](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#flutter-web-uses-javascript-sdk-v11).

## [HTTP Error Capture and Grouping](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#http-error-capture-and-grouping)

HTTP error types, messages, and capture rules have changed. Review HTTP error filters, grouping rules, and alert volumes after upgrading:

* `SentryHttpClient` reports failed HTTP status responses with the stable exception type `SentryHttpClientError`, and its message no longer starts with `Exception:`.
* `sentry_dio` uses the stable exception type `DioException`, including in obfuscated builds. Default error messages become `HTTP Client Error with status code: <code>` or `HTTP Client Error: <failure>`. Custom Dio string builders are preserved.
* `sentry_dio` now captures connection failures without a status code, such as timeouts, DNS failures, and certificate errors, when failed-request capture is enabled and the target matches. Caller-initiated cancellations without a status code are excluded.
* `sentry_dio` matches `failedRequestTargets` against the resolved full URL instead of the relative request path. Update patterns that assumed a path-only value.
* `sentry_supabase` uses the stable exception type `SentrySupabaseClientError`, and its message no longer starts with `Exception:`.

Dio events now include response status and metadata in `event.contexts.response`; response bodies remain on `hint.response`. Failed-request capture through `SentryHttpClient` and Dio excludes requests to the configured DSN host to prevent recursive error reporting.

## [Sensitive Content Masking](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#sensitive-content-masking)

The SDK now masks Flutter `SensitiveContent` widgets marked `sensitive` or `autoSensitive` by default in Session Replay and screenshots. A `notSensitive` widget still goes through the other masking rules; it does not automatically unmask its contents. Review captured output if your app uses these widgets with custom privacy rules.

## [Desktop Crash Reporting Uses Breakpad](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#desktop-crash-reporting-uses-breakpad)

On Windows and Linux, the default native crash backend changes to Breakpad. Native crash reports are uploaded when the application starts again, rather than by a separate Crashpad handler at crash time.

Breakpad handles crashes in the application process, without Crashpad's out-of-process isolation. It also lacks Crashpad's Windows Error Reporting (WER) and fast-fail coverage. Review crash-delivery expectations and test a crash followed by an application restart.

To retain Crashpad, set the `SENTRY_NATIVE_BACKEND` environment variable to `crashpad` in your local build environment and CI before building the application. For example:

**Linux**

```bash
SENTRY_NATIVE_BACKEND=crashpad flutter build linux
```

**Windows**

```powershell
$env:SENTRY_NATIVE_BACKEND = "crashpad"
flutter build windows
```

This is a build-time setting, not a Dart SDK initialization option.

## [Flutter Web Uses JavaScript SDK v11](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10.md#flutter-web-uses-javascript-sdk-v11)

Flutter web now bundles Sentry JavaScript SDK `11.0.0`. Browser sessions affected by unhandled errors are reported as `unhandled` rather than `crashed`. On web, `unhandled` is a terminal session status; native sessions treat unhandled Flutter errors as non-terminating.

For errors captured through the Dart SDK, web sessions are updated only after error sampling. Errors dropped by `sampleRate` do not update web release health.

Review web release-health dashboards and alerts that depend on crashed-session counts. This applies to unhandled errors captured from both Dart and JavaScript.

Keep using Flutter's `options.sendDefaultPii`. The Flutter SDK maps it to JavaScript v11's `dataCollection` settings and preserves the previous JavaScript privacy baseline when `sendDefaultPii` is `false`. You do not need to replace the Flutter option with a JavaScript configuration object.

If you initialize Sentry separately in JavaScript or call its APIs directly, also review the [JavaScript v10-to-v11 migration guide](https://docs.sentry.io/platforms/javascript/migration/v10-to-v11.md).

## Pages in this section

- [Interactive v10 Migration Guide](https://docs.sentry.io/platforms/dart/guides/flutter/migration/v9-to-v10/interactive.md)
