---
title: Error Analysis - Flutter
description: How to use CSQ Error Analysis in your Flutter apps
lastUpdated: 05 January 2026
source_url:
  html: https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/error-analysis/
  md: https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/error-analysis/index.md
---

## Prerequisites

### CSQ SDK is included

You must include the [CSQ SDK](../) first using the same integration method and understand [how the SDK works](../data-collection/).

### Updating to latest SDK version

To enable Error Analysis in your application and ensure optimal stability, make sure to always use the last SDK version.

### Screen tracking implemented

Tracking will start at the 1st screenview event, it is required to have screen tracking implemented. Make sure to follow the [Flutter Track screens](../track-screens/) sections.

### Reminder about User consent

If you are in the process of implementing the SDK for the 1st time, or if you choose to take this update as an opportunity to review your privacy-related implementation, ensure that you follow the [Flutter Privacy](../privacy/) section and use the [Opt-in API](../privacy/#opt-in) to get the user consent, otherwise no data will be collected.

## Get Started

### Start the SDK

You do not need to do anything to start the Error Analysis SDK, it will start itself with CSQ SDK.

### Validate SDK integration

When the SDK starts, you should see a log like this one:

```plaintext
// success case
CSLIB ℹ️ Info: Contentsquare Error Analysis [SDKVersionNumber] starting in app : [your.app.packageName]


// fail case
// << No public fail log
```

## API Errors

### Automatic network inspection

API Errors automatically collects failed network requests.

### Removing Personal Data in request URL path

By default, the API Errors feature collects the URL path of the failed API requests. To prevent the collection of Personal Data in the URL path, you can rewrite the request URL path with the `CSQ().setURLMaskingPatterns` SDK API.

Replace a step of the path - meaning between two slashes (/) - containing Personal Data with a variable:

* `:user_id` becomes CS\_ANONYMIZED\_USER\_ID
* `:address` becomes CS\_ANONYMIZED\_ADDRESS

#### Example

```dart
import 'package:contentsquare/csq.dart';


CSQ().setURLMaskingPatterns(patterns: [
  'https://www.contentsquare.com/users/:user_id/address/:address',
]);
```

##### Result

| URL before masking | URL after masking |
| - | - |
| `https://www.contentsquare.com/users/123/address/castle+black` | `https://www.contentsquare.com/users/CS_ANONYMIZED_USER_ID/address/CS_ANONYMIZED_ADDRESS` |

### Debugging and Logging

If in-app features are enabled, a info log should appear with the details of the event (see [Flutter Debugging and Logging](../in-app-features/#debugging-and-logging) section):

```plaintext
CSLIB ℹ️ Info: API Error - GET 401 https://api.client.com
```

### How API Errors works

#### Initialization

Our SDK automatically starts upon application launch and seamlessly captures failed network requests.

#### Configuration

Once started, our SDK fetches its config from our servers. It will start collecting data from network events if the API Errors setting is enabled in the config (this is handled by the Contentsquare team).

#### Tracking

The SDK monitors only the API Errors with response code 400 and above, and generates analytics data. These events are then locally stored, and eventually sent to our servers in batches.

Warning

To ensure that API Errors occurring at app launch are accurately tracked, ensure the session is being tracked (the user is included in tracked users and has not opted out), and a first screenview event has been sent.

Warning

During the initialization, the CSQ SDK overrides the `HttpOverrides.global` property.

If you have to override `HttpOverrides.global` in your app - [use a custom HttpOverrides](#use-a-custom-httpoverrides).

#### Sending data

For each network error, a new event will be sent in Analytics and Session Replay data. Check the following sections to learn more about how data is processed and sent:

* [Analytics requests](../data-collection/#sending-data)
* [Session Replay requests](../session-replay#requests)

### API Troubleshooting Details

API Errors troubleshooting details feature enhances your ability to collect additional information about API errors, facilitating faster troubleshooting.

With this feature, you can view three types of additional API error details in the Event Stream of Session Replay:

* The HTTP headers of the request and the response.
* The body (the data sent by the request or received in the response).
* The query parameters of the request endpoint (of the URL of the information you request for).

Note

This feature is part of [Experience Monitoring ↗](https://contentsquare.com/platform/experience-monitoring/), which is only available on Enterprise plans or as an add-on to Pro plans. Contact your Customer Success Manager or [sales ↗](https://contentsquare.com/request-a-demo/) to learn more.

See [API Troubleshooting Details ↗](https://support.contentsquare.com/hc/en-us/articles/37271885035537) for more details.

### Collected data points

Only network calls in error (response code 400 and above) will be collected.\
Here is the exhaustive list of data collected:

* URL (without query strings)
* HTTP method
* Response code
* Timestamp of the request
* Timestamp of the response
* HTTP headers of the request
* HTTP headers of the response
* HTTP body of the request
* HTTP body of the response
* Query parameters

### Known limitations and recommendations

#### Conflict with Firebase Performance Monitoring

##### Android

CSQ Error Analysis is not compatible with Firebase Performance Monitoring auto-collection. Only one of the two will log events, and usually, the events will be automatically logged by the Contentsquare Error Analysis. To log events to Firebase Performance Monitoring, we suggest [logging it manually ↗](https://rnfirebase.io/perf/usage#http-request-tracing).

##### iOS

CSQ Error Analysis is compatible with Firebase Performance auto-collection, but the HTTP body from the response won't be collected by the Error Analysis SDK.

CSQ Error Analysis may not be compatible with other network auto-collection tools.

### Use a custom HttpOverrides

Use `CSQHttpOverrides` if you need to override the global `HttpOverrides`.

```dart
import 'dart:io';
import 'package:contentsquare/csq.dart' show CSQHttpOverrides;


class YourCustomHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context);
  }
}


void main() {
  HttpOverrides.global = CSQHttpOverrides(
    httpOverrides: YourCustomHttpOverrides(),
  );
}
```

Note

Your custom `HttpOverrides` will function as expected under the normal conditions. The `CSQHttpOverrides` will operate exclusively as a proxy.

Note

If during the initialization it is observed that another `HttpOverrides` is being used globally and it is not `CSQHttpOverrides`, it will be automatically replaced with `CSQHttpOverrides`, as illustrated in the example.

## Error Reporter

### Handle the Flutter errors

You can collect unhandled errors from the framework by using the [FlutterError.onError ↗](https://api.flutter.dev/flutter/foundation/FlutterError/onError.html) callback. However, errors that occur outside of Flutter's callbacks, such as asynchronous errors, will not be captured. To handle these, consider implementing the [PlatformDispatcher.onError ↗](https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/onError.html) or [runZonedGuarded ↗](https://api.flutter.dev/flutter/dart-async/runZonedGuarded.html) callbacks.

#### Example

* Using PlatformDispatcher.onError

  ```dart
  import 'package:contentsquare/csq.dart';


  void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    FlutterError.onError = (FlutterErrorDetails details) {
      // Collects Flutter errors
      CSQ().collectFlutterError(details: details);
    };
    WidgetsBinding.instance.platformDispatcher.onError = (exception, stackTrace) {
      // Collects all unhandled errors from the root isolate, including platform-level errors
      CSQ().collectError(error: exception, stackTrace: stackTrace);
      return false;
    };
    runApp(MyApp());
  }
  ```

* Using runZonedGuarded

  ```dart
  import 'package:contentsquare/csq.dart';


  void main() async {
    runZonedGuarded(() {
      FlutterError.onError = (FlutterErrorDetails details) {
        // Collects Flutter errors
        CSQ().collectFlutterError(details: details);
      };
      runApp(MyApp());
    }, (error, stack) {
      // Collects all unhandled errors in the zone
      CSQ().collectError(error: error, stackTrace: stack);
    });
  }
  ```

#### Flutter error presentation

CSQ automatically [presents ↗](https://api.flutter.dev/flutter/foundation/FlutterError/presentError.html) the Flutter errors. You can disable it by using the optional `presentErrorDetails` parameter in `collectFlutterError` API.

```dart
import 'package:contentsquare/csq.dart';


CSQ().collectFlutterError(details: details, presentErrorDetails: false);
```

#### Compatibility with Firebase Crashlytics

Integrating Crashlytics as an additional error reporting solution is straightforward: include the corresponding instruction within each callback.

##### Example with Firebase Crashlytics

```dart
import 'package:contentsquare/csq.dart';


void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    FlutterError.onError = (FlutterErrorDetails details) {
      CSQ().collectFlutterError(details: details, presentErrorDetails: false);
      FirebaseCrashlytics.instance.recordFlutterError(details);
    };
    WidgetsBinding.instance.platformDispatcher.onError = (exception, stackTrace) {
      CSQ().collectError(error: exception, stackTrace: stackTrace);
      FirebaseCrashlytics.instance.recordError(exception, stackTrace);
      return false;
    };
    runApp(MyApp());
  }
```

### Validate integration

1. Enable the [in-app features](../in-app-features/#enable-in-app-features).
2. Run your application. You should see a log printed in the console:

```plaintext
┌───────────────────────────────────────────────────────────────────────────────
│ ℹ️ INFO ℹ️ (CSLIB)
├───────────────────────────────────────────────────────────────────────────────
│ Errors Reporter module has started.
└───────────────────────────────────────────────────────────────────────────────
```

#### Validate error reporting

With [in-app features](../in-app-features/#enable-in-app-features) enabled, any errors occurring in your application should generate a log in the console:

```plaintext
┌───────────────────────────────────────────────────────────────────────────────
│ ℹ️ INFO ℹ️ (CSLIB)
├───────────────────────────────────────────────────────────────────────────────
│ Error was collected.
│ Exception: type 'String' is not a subtype of type 'int' in type cast
└───────────────────────────────────────────────────────────────────────────────
```

### Symbolization and de-obfuscation

Note

The following step are only needed if you are using the `--split-debug-info` or `--obfuscate` options with the `flutter build` commands

To be able to read errors from an application built with Flutter obfuscation and/or de-symbolisation, you will need to upload the debug files to Contentsquare.

1. [Enable the `contentsquare_cli` plugin](../contentsquare-cli/#installation)

2. [Run the upload command](../contentsquare-cli/#upload-debug-files-command)

The upload command must be executed immediately after the Flutter build.

Automating the upload

As Flutter overwrites debug files for the same platform with each build, if you fail to upload the debug files in time, you won't be able to read errors from the previous release.

You should run the upload command within your CI/CD pipeline or build script after every release build.

#### Minimum required Flutter version

* Android: 3.10.6
* iOS: 3.13.0

### How Error Reporter works

#### Initialization

Error Reporter is started automatically and begins to collect the reported errors when your application is launched

#### Configuration

Once started, our SDK fetches its configuration from our servers. It will start reporting errors if the Error Reporter setting is enabled (this is handled by the Contentsquare team).

You have to implement an error handler strategy and collect the received errors. See [Flutter errors](#handle-the-flutter-errors) for examples

#### Reporting

When an error occurs, a report is created and stored locally in the device. The report is sent to our servers as soon as possible and then removed from the local storage.

Warning

To make sure errors are correctly tracked, the session has to be tracked (included in tracked users and not opted-out) and a first screenview event has to be sent. See [Track screens](../track-screens/) for more details.

#### Sending error data

For each error, a new event will be sent to analytics and Session Replay data when the network conditions allow for the server to be reached.

### Native crashes

Crashes from the native parts of your application can be captured with additional setup.

See 📚 [iOS Crash Reporter](https://docs.contentsquare.com/en/csq-sdk-ios/experience-analytics/error-analysis/#crash-reporter).

See 📚 [Android Crash Reporter](https://docs.contentsquare.com/en/csq-sdk-android/experience-analytics/error-analysis/#crash-reporter).

### WebView errors

Errors occurring in web pages loaded in WebViews can be collected if Webview tracking is setup in your app.

See 📚 [Webview Tracking implementation](https://docs.contentsquare.com/en/webview-tracking-tag/).

Once WebView tracking is implemented, errors collection can be set up.

See 📚 [Errors (in WebView)](https://docs.contentsquare.com/en/webview-tracking-tag/error-analysis/)
