# Reporting Crashes

### Enable or disable crash reporting

Use `FeatureState` to turn crash reporting on or off. Reporting only runs when the state is enabled and the user has consented (if you use consent).

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setState(FeatureState.Enabled)
CrashReportingKmp.setState(FeatureState.Disabled)
```

{% endcode %}

### Report non-fatal exceptions

Report caught exceptions so they appear in the dashboard with severity and optional grouping:

{% code title="Kotlin" %}

```kotlin
try {
    riskyOperation()
} catch (e: Exception) {
    CrashReportingKmp.reportException(
        exception = e,
        userAttributes = mapOf("screen" to "Checkout", "userId" to "123"),
        fingerprint = "payment_failed",  // optional, for grouping
        level = NonFatalLevel.Error
    )
    throw e
}
```

{% endcode %}

**Parameters:**

* **exception**: The `Throwable` to report.
* **userAttributes**: Key-value context (e.g. screen, user id) attached to the report.
* **fingerprint**: Optional custom grouping key for similar issues.
* **level**: `NonFatalLevel.Critical`, `Error`, `Warning`, or `Info`.

### User attributes for crash reports

Set attributes that are attached to all subsequent crash reports:

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setUserAttributes(mapOf("environment" to "staging", "version" to "2.0"))
CrashReportingKmp.addUserAttribute("screen", "Settings")
CrashReportingKmp.removeUserAttribute("screen")
CrashReportingKmp.clearAllUserAttributes()
```

{% endcode %}

### User consent

For GDPR and privacy, you can gate sending crash reports on user consent:

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setUserConsent(true)   // allow sending
CrashReportingKmp.setUserConsent(false)  // do not send
val consented = CrashReportingKmp.hasUserConsent()
```

{% endcode %}

When consent is false, crash reports are not sent even if crash reporting is enabled.

### Callbacks

**Before sending a report** – add or collect extra context at report time:

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setOnBeforeSendReport {
    mapOf("customKey" to "value")
}
CrashReportingKmp.clearOnBeforeSendReport()
```

{% endcode %}

**Before/after non-fatal report** – observe or modify non-fatal reporting:

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setOnWillReportNonFatal { exception, userAttributes, fingerprint, level ->
    // Modify or prevent reporting
}
CrashReportingKmp.clearOnWillReportNonFatal()

CrashReportingKmp.setOnDidReportNonFatal { exception, userAttributes, fingerprint, level, wasReported ->
    // e.g. analytics
}
CrashReportingKmp.clearOnDidReportNonFatal()
```

{% endcode %}

### Android-only: NDK and ANR

**NDK crashes** (native C/C++ crashes):

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setNDKCrashesState(FeatureState.Enabled)
```

{% endcode %}

**ANR** (Application Not Responding):

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setANRState(FeatureState.Enabled)
```

{% endcode %}

Both are no-ops on iOS.

### Crash-time handler (iOS only)

On iOS you can set a handler that runs at crash time to add attributes. It runs in a signal handler, so it must be very fast and avoid allocations and I/O:

{% code title="Kotlin" %}

```kotlin
CrashReportingKmp.setCrashTimeHandler {
    mapOf("crashKey" to "value")
}
CrashReportingKmp.clearCrashTimeHandler()
```

{% endcode %}

This is a no-op on Android.
