> For the complete documentation index, see [llms.txt](https://cmp.docs.sirdata.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cmp.docs.sirdata.net/en/mobile-apps-native-sdk/mobile-sdk/logging.md).

# Logging

The SDK has no verbose mode, and there is nothing to turn on. On Android it logs one line when the configuration has loaded; otherwise it writes a line only when something needs your attention.

On Android, look in Logcat for the tags `SirDataCMP` and `SirDataCMPManager`:

* the publisher configuration loaded (`Config loaded successfully`), or failed to load, with the reason (`Config load failed: …`), both on the `SirDataCMPManager` tag;
* a consent submission that failed (`Consent submission failed: …`);
* `TC string generation failed: /consent-string …`: despite its wording, the server archive of a recorded choice failed. The TC string itself is encoded on the device and stored. The line is written when the next choice is recorded; `getLastTcStringError()` returns the same message;
* a stored TC string that could not be read back;
* a consent adapter that failed to forward a choice, under the adapter's name;
* a call to `initialize`, `shutdown` or `setCcpaOptOut` made off the main thread.

The configuration failure can also be read in code: `SirDataCMPApi.getInitError()` is a `StateFlow<String?>` — `null` while the configuration loads and after it loaded, the error message once a load has failed. The next `initialize` clears it.

```kotlin
lifecycleScope.launch {
    SirDataCMPApi.getInitError().collect { error ->
        if (error != null) Log.w("CMP", "Configuration failed to load: $error")
    }
}
```

On iOS, look in the Xcode console for lines starting with `[CMP]`: the same adapter failures, main-thread violations and unreadable stored TC string, plus a TCF or GPP command called off the main thread. An initialization failure is not logged on iOS: read it with `IosCMPApi.shared.getInitError()` — `nil` while the configuration loads and after it loaded, the error message once a load has failed — once `getConsentState()` has left `LOADING`. In 2.0.0 the SDK sets it on the main thread just after that change, so it may still be `nil` at the very moment the state turns `READY`; the next release sets it before.

## `debugMode`

`debugMode` does not change what is logged. It makes a call to `initialize`, `shutdown` or `setCcpaOptOut` made off the main thread throw instead of only being logged, so the fault surfaces in your own debug build. Enable it in debug builds only: the SDK does not check the build type, and on iOS the exception terminates the app.

```kotlin
// Android — tie it to your build type (with AGP 8, BuildConfig needs
// buildFeatures { buildConfig = true } in your app module)
val config = SirDataCMPConfig.Builder(partnerId, configId)
    .debugMode(BuildConfig.DEBUG)
    .build()
```

```swift
// iOS — debug builds only
let config = IosCMPConfig.Builder(partnerId: partnerId, configId: configId)
    #if DEBUG
    .debugMode(debugMode: true)
    #endif
    .build()
```

React Native: do not pass `debugMode: true` on Android in 2.0.0 and 2.0.1. The bridge calls `initialize` off the main thread, so with `debugMode` the promise rejects with `E_INIT` — see [Troubleshooting](/en/mobile-apps-native-sdk/mobile-sdk/troubleshooting.md). See also [Setup — React Native](/en/mobile-apps-native-sdk/mobile-sdk/react-native-setup.md).

## Reading the display decision

If the banner does not show, the decision object says why before any log does:

```kotlin
// Android — awaitConsentDisplayDecision() suspends: call it from a coroutine
lifecycleScope.launch {
    val decision = SirDataCMPApi.awaitConsentDisplayDecision()
    Log.d("CMP", "display=${decision.shouldDisplay} workflow=${decision.workflow} reason=${decision.reason}")
}
```

An active capping window, a stored consent that still covers every active purpose, or GDPR not applying are all normal reasons for a banner not to appear.

## Never log consent as user data

The TC string and the per-purpose bit fields describe an identified user's choices. They belong in debug logs during development, not in a production crash reporter or analytics event.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://cmp.docs.sirdata.net/en/mobile-apps-native-sdk/mobile-sdk/logging.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
