> ## Documentation Index
> Fetch the complete documentation index at: https://docs.permutive.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Solutions to common issues when integrating the Permutive Android SDK

This guide covers common issues you may encounter when integrating the Permutive Android SDK and how to resolve them.

<Info>
  **Quick Diagnostics:** Enable debug logging before troubleshooting:

  ```kotlin theme={"dark"}
  permutive.setDeveloperMode(true)
  ```

  Or via ADB:

  ```bash theme={"dark"}
  adb shell setprop log.tag.Permutive VERBOSE
  adb logcat -s Permutive
  ```
</Info>

## Initialization Issues

<AccordionGroup>
  <Accordion title="Error fetching configuration - please check that your workspace id & API key is correct">
    **Symptoms:**

    ```
    D/Permutive: Error fetching configuration - please check that your workspace id & API key is correct, or contact customer support (Http error: 404)
    ```

    **Causes:**

    1. Incorrect Workspace ID or API Key
    2. Using deprecated `projectId` instead of `workspaceId`
    3. Android not enabled for your workspace

    **Solutions:**

    **1. Verify Credentials**

    ```kotlin theme={"dark"}
    // ❌ Wrong: Using deprecated projectId
    val permutive = Permutive.Builder()
        .projectId(UUID.fromString("..."))  // DEPRECATED
        .build()

    // ✅ Correct: Use workspaceId
    val permutive = Permutive(
        context = this,
        workspaceId = UUID.fromString("YOUR_WORKSPACE_ID"),
        apiKey = UUID.fromString("YOUR_API_KEY")
    )
    ```

    **2. Check Credentials Format**

    Ensure your IDs are valid UUIDs (format: 8-4-4-4-12 hexadecimal digits):

    ```kotlin theme={"dark"}
    // Example: "550e8400-e29b-41d4-a716-446655440000"

    // ❌ Wrong: Not a UUID
    workspaceId = UUID.fromString("12345")  // Throws exception

    // ✅ Correct: Valid UUID
    workspaceId = UUID.fromString("550e8400-e29b-41d4-a716-446655440000")
    ```

    **3. Enable Android**

    Contact your Customer Success Manager to verify Android is enabled for your workspace.
  </Accordion>

  <Accordion title="Multiple Permutive instances detected">
    **Symptoms:** Events tracked multiple times, undefined behavior.

    **Cause:** Creating more than one `Permutive` instance.

    **Solution:** Use a singleton pattern:

    <CodeGroup>
      ```kotlin Kotlin theme={"dark"}
      class MyApplication : Application() {
          val permutive by lazy {
              Permutive(
                  context = this,
                  workspaceId = YOUR_WORKSPACE_ID,
                  apiKey = YOUR_API_KEY
              )
          }
      }

      // Access from activities
      class MyActivity : AppCompatActivity() {
          private val permutive by lazy {
              (application as MyApplication).permutive
          }
      }
      ```

      ```java Java theme={"dark"}
      public class MyApplication extends Application {
          private volatile Permutive permutive;

          public Permutive getPermutive() {
              if (permutive == null) {
                  synchronized (this) {
                      if (permutive == null) {
                          permutive = new Permutive.Builder()
                              .context(this)
                              .workspaceId(YOUR_WORKSPACE_ID)
                              .apiKey(YOUR_API_KEY)
                              .build();
                      }
                  }
              }
              return permutive;
          }
      }
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Event Tracking Issues

<AccordionGroup>
  <Accordion title="Schema validation failed">
    **Symptoms:**

    ```
    D/Permutive: Error publishing event with name "Pageview":
    D/Permutive: Code: 1007
    D/Permutive: Status: BadRequest
    D/Permutive: Cause: Schema validation failed with reason(s): [#: extraneous key [publishDate] is not permitted;#/article/categories: expected type: JSONArray, found: String]
    ```

    **Causes:**

    1. Property name doesn't match dashboard schema
    2. Property type doesn't match dashboard schema
    3. Property not defined in dashboard

    **Solutions:**

    **1. Check Property Names** (case-sensitive):

    ```kotlin theme={"dark"}
    // ❌ Wrong: Typo in property name
    EventProperties.from("publishDate" to date)  // Schema expects "published_at"

    // ✅ Correct: Exact match with schema
    EventProperties.from("published_at" to date)
    ```

    **2. Check Property Types:**

    ```kotlin theme={"dark"}
    // ❌ Wrong: String instead of Array
    EventProperties.from("categories" to "sports")  // Schema expects List<String>

    // ✅ Correct: Array type
    EventProperties.from("categories" to listOf("sports", "football"))
    ```

    **3. Verify Schema in Dashboard:**

    1. Log into Permutive dashboard
    2. Navigate to Events
    3. Find your event type
    4. Verify property names and types match your code
  </Accordion>

  <Accordion title="Events not appearing in dashboard">
    **Symptoms:** Events show as "Accepted" in logs but don't appear in dashboard.

    **Causes:**

    1. Dashboard filter settings
    2. Time lag (events can take up to 5 minutes)
    3. Wrong workspace/environment

    **Solutions:**

    1. **Check Logs**: Verify events are accepted:
       ```
       D/Permutive: Published events with names (Pageview) (Accepted: 1 / 1)
       ```

    2. **Wait**: Events may take up to 5 minutes to appear

    3. **Check Dashboard Filters**:
       * Verify date range includes now
       * Check workspace selection
       * Clear any active filters

    4. **Verify Environment**: Ensure you're using production workspace ID
  </Accordion>

  <Accordion title="Invalid event name">
    **Symptoms:**

    ```
    IllegalArgumentException: Invalid event name "My Event": must contain only the characters [a-zA-Z0-9_]
    ```

    **Cause:** Event name contains invalid characters.

    **Solution:** Event names must contain only: `a-z`, `A-Z`, `0-9`, `_`

    ```kotlin theme={"dark"}
    // ❌ Wrong: Contains spaces and special characters
    tracker.track("My Event!", properties)
    tracker.track("page-view", properties)

    // ✅ Correct: Only valid characters
    tracker.track("MyEvent", properties)
    tracker.track("page_view", properties)
    tracker.track("PageView123", properties)
    ```
  </Accordion>
</AccordionGroup>

## Identity Issues

<AccordionGroup>
  <Accordion title="Identity not resolving">
    **Symptoms:** Setting identity doesn't merge user data from other devices.

    **Causes:**

    1. Network connectivity issues
    2. Alias not previously used
    3. Timing - resolution takes a moment

    **Solutions:**

    1. **Check Logs**:
       ```
       D/Permutive: Identified user with aliases: email_sha256, internal_id
       ```

    2. **Verify Network**: Ensure device has connectivity

    3. **Wait**: Identity resolution isn't instant, allow a few seconds

    4. **Debug**:
       ```kotlin theme={"dark"}
       permutive.setDeveloperMode(true)
       permutive.setIdentity(
           listOf(Alias.create("email_sha256", emailHash, 0))
       )
       // Check logs for "Identified user" message
       ```
  </Accordion>

  <Accordion title="Unhashed PII error">
    **Problem:** Accidentally sending personally identifiable information.

    **Solution:** Always hash PII before setting as identity:

    ```kotlin theme={"dark"}
    import java.security.MessageDigest

    fun hashEmail(email: String): String {
        val normalized = email.trim().lowercase()
        val bytes = MessageDigest.getInstance("SHA-256")
            .digest(normalized.toByteArray())
        return bytes.joinToString("") { "%02x".format(it) }
    }

    // ❌ Wrong: Plain text email
    permutive.setIdentity(
        listOf(Alias.create("email", "user@example.com", 0))  // DON'T!
    )

    // ✅ Correct: Hashed email
    val emailHash = hashEmail("user@example.com")
    permutive.setIdentity(
        listOf(Alias.create("email_sha256", emailHash, 0))
    )
    ```
  </Accordion>
</AccordionGroup>

## Cohort and Activation Issues

<AccordionGroup>
  <Accordion title="Empty cohorts list">
    **Symptoms:** `currentCohorts` returns empty list.

    **Causes:**

    1. SDK just initialized - cohorts haven't synced yet
    2. User hasn't triggered events to qualify for cohorts
    3. Network issues

    **Solutions:**

    1. **Wait for Initialization**:
       ```kotlin theme={"dark"}
       // Don't check cohorts immediately
       Handler(Looper.getMainLooper()).postDelayed({
           val cohorts = permutive.currentCohorts
           Log.d("Debug", "Cohorts: ${cohorts.size}")
       }, 3000)
       ```

    2. **Use TriggersProvider**: For reactive updates:
       ```kotlin theme={"dark"}
       val trigger = triggersProvider.triggerAction("cohort_id") { isInCohort ->
           // Called when cohort status changes
       }
       ```

    3. **Track Events**: User needs to trigger events to qualify for cohorts
  </Accordion>

  <Accordion title="Contextual cohorts not appearing">
    **Symptoms:** `dfp_contextual` or `appnexus_adserver_contextual` are empty.

    **Causes:**

    1. Feature not enabled
    2. SDK version too old
    3. Not tracking pages with URLs
    4. Classification in progress

    **Solutions:**

    1. **Check SDK Version**:
       * Core: 1.10.0+
       * Google Ads: 2.2.0+
       * AppNexus: 1.7.0+

    2. **Verify Feature Enabled**: Contact Customer Success Manager

    3. **Track with URLs**:
       ```kotlin theme={"dark"}
       // ❌ Wrong: No URL
       val pageTracker = permutive.trackPage(title = "Article Title")

       // ✅ Correct: Include URL
       val pageTracker = permutive.trackPage(
           title = "Article Title",
           url = Uri.parse("https://example.com/article")
       )
       ```

    4. **Wait for Classification**: First analysis takes 1-2 seconds

    5. **Check URL Accessibility**: URL must be publicly accessible
  </Accordion>
</AccordionGroup>

## Ad Integration Issues

<AccordionGroup>
  <Accordion title="Ads not receiving cohorts">
    **Symptoms:** Ads load but don't seem to be targeted.

    **Causes:**

    1. Not using add-on library helper methods
    2. Cohorts not ready when ad request made
    3. Dashboard activation configuration

    **Solutions:**

    **1. Use Helper Methods**

    ```kotlin theme={"dark"}
    // ❌ Wrong: Manual ad request without Permutive
    val adRequest = AdManagerAdRequest.Builder().build()

    // ✅ Correct: Use Permutive helper
    val adRequest = AdManagerAdRequest.Builder()
        .addPermutiveTargeting(permutive)
        .build()
    ```

    **2. Verify Logs**

    Look for:

    ```
    D/Permutive: Permutive segments appended to Google Ad request: 123, 456, 789
    ```

    If this doesn't appear, cohorts aren't being added.

    **3. Check Activations**

    ```kotlin theme={"dark"}
    val activations = permutive.currentActivations
    val gamCohorts = activations["dfp"]

    if (gamCohorts.isNullOrEmpty()) {
        Log.w("Debug", "No GAM activations available")
        // Either cohorts not ready or not activated for GAM
    }
    ```
  </Accordion>
</AccordionGroup>

## Performance Issues

<AccordionGroup>
  <Accordion title="App slowdown">
    **Symptoms:** App performance degrades after SDK integration.

    **Causes:**

    1. Creating multiple Permutive instances
    2. Not closing PageTrackers/MediaTrackers
    3. Memory leaks from unclosed TriggerActions

    **Solutions:**

    **1. Use Singleton** (see "Multiple Permutive instances detected" above)

    **2. Always Close Trackers**

    ```kotlin theme={"dark"}
    class MyActivity : AppCompatActivity() {
        private lateinit var pageTracker: PageTracker

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            pageTracker = permutive.trackPage(...)
        }

        override fun onDestroy() {
            super.onDestroy()
            pageTracker.close()  // IMPORTANT!
        }
    }
    ```

    **3. Close Triggers**

    ```kotlin theme={"dark"}
    class MyActivity : AppCompatActivity() {
        private val triggers = mutableListOf<TriggerAction>()

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            triggers.add(triggersProvider.triggerAction("cohort") { /*...*/ })
        }

        override fun onDestroy() {
            super.onDestroy()
            triggers.forEach { it.close() }  // IMPORTANT!
            triggers.clear()
        }
    }
    ```
  </Accordion>

  <Accordion title="Memory leaks">
    **Symptoms:** App memory usage grows over time.

    **Cause:** Not closing SDK resources.

    **Solution:** Use Android Studio's Profiler to identify leaks, then ensure all SDK resources are closed:

    * `PageTracker.close()`
    * `MediaTracker.stop()`
    * `AdTracker.completion()`
    * `TriggerAction.close()`
  </Accordion>
</AccordionGroup>

## Build Issues

<AccordionGroup>
  <Accordion title="ProGuard/R8 issues">
    **Symptoms:** App crashes in release build with minification enabled.

    **Cause:** SDK classes being stripped by ProGuard/R8.

    **Solution:** The SDK includes consumer ProGuard rules automatically. If you're still experiencing issues:

    1. **Verify consumer rules are applied**:
       ```groovy theme={"dark"}
       android {
           buildTypes {
               release {
                   minifyEnabled true
                   proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
               }
           }
       }
       ```

    2. **Test with debug logging**:
       ```kotlin theme={"dark"}
       if (BuildConfig.DEBUG) {
           permutive.setDeveloperMode(true)
       }
       ```
  </Accordion>

  <Accordion title="Duplicate class errors">
    **Symptoms:**

    ```
    Duplicate class com.permutive.android.X found in modules...
    ```

    **Causes:**

    1. Multiple SDK versions in dependencies
    2. Transitive dependency conflicts

    **Solutions:**

    **1. Check Dependencies**

    ```bash theme={"dark"}
    ./gradlew app:dependencies
    ```

    Look for multiple versions of Permutive libraries.

    **2. Force Version Resolution**

    ```kotlin theme={"dark"}
    configurations.all {
        resolutionStrategy {
            force("com.permutive.android:core:1.11.3")
            force("com.permutive.android:google-ads:2.2.0")
        }
    }
    ```
  </Accordion>
</AccordionGroup>

## Debugging Tips

<Tabs>
  <Tab title="Enable Logging">
    ```kotlin theme={"dark"}
    // Enable Permutive debug logs
    permutive.setDeveloperMode(true)

    // Enable network logging (if using OkHttp)
    val loggingInterceptor = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY
    }
    ```
  </Tab>

  <Tab title="Check SDK Version">
    ```kotlin theme={"dark"}
    // Log SDK version
    Log.d("Debug", "Permutive SDK Version: ${BuildConfig.VERSION_NAME}")
    ```
  </Tab>

  <Tab title="Verify Metrics">
    ```kotlin theme={"dark"}
    val metrics = permutive.currentMetrics
    Log.d("Debug", "SDK Metrics: $metrics")
    ```
  </Tab>
</Tabs>

## Getting Help

If you're still experiencing issues:

1. Enable debug logging and capture logs
2. Note the SDK version you're using
3. Document steps to reproduce the issue
4. Gather SDK version, device info, and error logs

**Contact Support:**

* [Support](mailto:support@permutive.com)

<CardGroup cols={2}>
  <Card title="Verification Guide" icon="circle-check" href="/sdks/mobile/android/getting-started/verification">
    Comprehensive integration verification
  </Card>

  <Card title="Migration Guide" icon="arrow-up" href="/sdks/mobile/android/guides/migration/v1-9-to-v1-10">
    Upgrade to the latest SDK version
  </Card>
</CardGroup>
