Skip to main content
This guide covers common issues you may encounter when integrating the Permutive Android SDK and how to resolve them.
Quick Diagnostics: Enable debug logging before troubleshooting:
permutive.setDeveloperMode(true)
Or via ADB:
adb shell setprop log.tag.Permutive VERBOSE
adb logcat -s Permutive

Initialization Issues

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
// ❌ 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 FormatEnsure your IDs are valid UUIDs (format: 8-4-4-4-12 hexadecimal digits):
// 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 AndroidContact your Customer Success Manager to verify Android is enabled for your workspace.
Symptoms: Events tracked multiple times, undefined behavior.Cause: Creating more than one Permutive instance.Solution: Use a singleton pattern:
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
    }
}

Event Tracking Issues

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):
// ❌ 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:
// ❌ 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
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
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, _
// ❌ 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)

Identity Issues

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:
    permutive.setDeveloperMode(true)
    permutive.setIdentity(
        listOf(Alias.create("email_sha256", emailHash, 0))
    )
    // Check logs for "Identified user" message
    
Problem: Accidentally sending personally identifiable information.Solution: Always hash PII before setting as identity:
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", "[email protected]", 0))  // DON'T!
)

// ✅ Correct: Hashed email
val emailHash = hashEmail("[email protected]")
permutive.setIdentity(
    listOf(Alias.create("email_sha256", emailHash, 0))
)

Cohort and Activation Issues

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:
    // 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:
    val trigger = triggersProvider.triggerAction("cohort_id") { isInCohort ->
        // Called when cohort status changes
    }
    
  3. Track Events: User needs to trigger events to qualify for cohorts
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:
    // ❌ 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

Ad Integration Issues

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
// ❌ Wrong: Manual ad request without Permutive
val adRequest = AdManagerAdRequest.Builder().build()

// ✅ Correct: Use Permutive helper
val adRequest = AdManagerAdRequest.Builder()
    .addPermutiveTargeting(permutive)
    .build()
2. Verify LogsLook 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
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
}

Performance Issues

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
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
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()
    }
}
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()

Build 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:
    android {
        buildTypes {
            release {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    }
    
  2. Test with debug logging:
    if (BuildConfig.DEBUG) {
        permutive.setDeveloperMode(true)
    }
    
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
./gradlew app:dependencies
Look for multiple versions of Permutive libraries.2. Force Version Resolution
configurations.all {
    resolutionStrategy {
        force("com.permutive.android:core:1.10.0")
        force("com.permutive.android:google-ads:2.2.0")
    }
}

Debugging Tips

// Enable Permutive debug logs
permutive.setDeveloperMode(true)

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

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: