Skip to main content
This guide covers common issues and their solutions when integrating the Permutive iOS SDK.

Installation Issues

Error: Unable to find a specification for 'Permutive_iOS'Solutions:
  1. Update your CocoaPods repo:
    pod repo update
    
  2. Ensure CocoaPods is version 1.9.1 or later:
    pod --version
    
  3. Clear the cache:
    pod cache clean --all
    pod install
    
Error: Xcode cannot resolve the package.Solutions:
  1. Check your network connection
  2. Reset package caches: File → Packages → Reset Package Caches
  3. Verify the URL is correct: https://github.com/permutive-engineering/permutive-ios-spm
  4. Try removing and re-adding the package
Error: No such module 'Permutive_iOS'Solutions:
  1. Clean build folder: Product → Clean Build Folder (⇧⌘K)
  2. For CocoaPods: Ensure you opened the .xcworkspace file, not .xcodeproj
  3. Restart Xcode
  4. For SPM: Reset package caches
Error: Bitcode-related build errors.Solution: Disable Bitcode in your target’s Build Settings:
  • Set Enable Bitcode to No
Bitcode is no longer required for App Store submission.
Error: Duplicate symbol errors during linking.Solutions:
  1. Ensure you’re not mixing CocoaPods and SPM for Permutive
  2. Check for conflicting library versions
  3. Clean derived data: rm -rf ~/Library/Developer/Xcode/DerivedData

Initialization Issues

Problem: Options(apiKey:organisationId:workspaceId:) returns nil.Causes:
  • Empty or whitespace-only credentials
  • Invalid credential format
Solution: Verify your credentials:
let apiKey = "<your-api-key>".trimmingCharacters(in: .whitespacesAndNewlines)
let orgId = "<your-org-id>".trimmingCharacters(in: .whitespacesAndNewlines)
let workspaceId = "<your-workspace-id>".trimmingCharacters(in: .whitespacesAndNewlines)

guard !apiKey.isEmpty, !orgId.isEmpty, !workspaceId.isEmpty else {
    print("Credentials are empty")
    return
}

guard let options = Options(apiKey: apiKey, organisationId: orgId, workspaceId: workspaceId) else {
    print("Invalid credential format")
    return
}
Problem: No error, but SDK doesn’t seem to work.Solution: Enable debug logging and check for errors:
options.logModes = LogMode.all

Permutive.shared.start(with: options) { error in
    if let error = error {
        print("Initialization failed: \(error)")
    } else {
        print("SDK initialized successfully")
    }
}
Problem: Initialization fails with network error.Solutions:
  1. Check device network connectivity
  2. Verify no firewall is blocking Permutive domains
  3. Check if running on simulator with network issues
  4. Retry initialization:
    Permutive.shared.start(with: options) { error in
        if error != nil {
            // Retry after delay
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                Permutive.shared.start(with: options, completion: nil)
            }
        }
    }
    
Problem: Events tracked before initialization completes are lost.Solution: Wait for the completion callback:
Permutive.shared.start(with: options) { error in
    guard error == nil else { return }
    // Now safe to track
    self.startTracking()
}

Tracking Issues

Error:
Permutive: [error] Schema validation failed with reason(s): [#: extraneous key [invalid_key] is not permitted]
Causes:
  • Property names don’t match schema
  • Property types don’t match schema
  • Extra properties not in schema
Solutions:
  1. Check your Permutive dashboard for the correct schema
  2. Verify property names exactly (case-sensitive)
  3. Remove any extra properties
  4. Verify property types match (string, int, bool, etc.)
Error: EventProperties constructor throws an exception.Causes:
  • Unsupported value types
  • Invalid nested objects
Solutions: Ensure all values are supported types:
// Supported types:
// String, Int, Float, Double, Bool, Date, EventProperties, and arrays of these

// ❌ Wrong - Custom object
let props = try EventProperties(["user": myUserObject])

// ✅ Correct - Primitive types
let props = try EventProperties([
    "user_id": user.id,           // String
    "user_name": user.name,       // String
    "age": user.age               // Int
])
Problem: No Pageview event in logs.Solutions:
  1. Ensure resume() is called:
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        try? pageTracker?.resume()  // Must call this
    }
    
  2. Check PageTracker was created successfully
  3. Verify SDK is initialized before creating PageTracker
  4. Enable debug logging
Problem: PageTracker stops when navigating or creating new trackers.Cause: Only one PageTracker/MediaTracker can be active at a time.Solution: This is expected behavior. Creating a new tracker stops any existing one. Design your flow accordingly.
Problem: Console is silent, no Permutive logs appear.Solutions:
  1. Confirm logModes is set before start():
    options.logModes = LogMode.all  // Must set before start()
    Permutive.shared.start(with: options) { ... }
    
  2. Check Xcode console filter isn’t hiding messages
  3. Verify SDK is actually being initialized

Cohort and Activation Issues

Problem: Permutive.shared.cohorts returns an empty set.Causes:
  • SDK just initialized (cohorts not yet synced)
  • No events tracked yet
  • User doesn’t qualify for any cohorts
Solutions:
  1. Wait a few seconds after initialization
  2. Track some events to generate data
  3. Use TriggerProvider for reactive updates
  4. Check your dashboard for cohort definitions
Problem: User is in a cohort but it doesn’t appear in activations.Cause: Not all cohorts are activated for all platforms.Solution: Check your Permutive dashboard configuration. Activations must be explicitly configured for each platform (GAM, Xandr, etc.).
Problem: dfp_contextual or appnexus_adserver_contextual is empty.Solutions:
  1. Verify contextual features are enabled (contact your CSM)
  2. Update to SDK 2.0.0+
  3. Ensure PageTracker has a valid, publicly accessible URL
  4. Allow time for content analysis (1-2 seconds)
  5. Check debug logs for classification errors

Identity Issues

Error: setIdentityForIDFA throws an error.Cause: IDFA is all zeros (tracking denied/restricted).Solution:
if #available(iOS 14, *) {
    let status = ATTrackingManager.trackingAuthorizationStatus
    guard status == .authorized else {
        // Use alternative identity
        return
    }
}

let idfa = ASIdentifierManager.shared().advertisingIdentifier
guard idfa != UUID(uuidString: "00000000-0000-0000-0000-000000000000") else {
    // IDFA not available
    return
}

try Permutive.shared.setIdentityForIDFA(idfa)
Problem: Alias with certain tags is ignored.Cause: Reserved tags: appnexus, amp, gigya, sailthru, aaidSolution: Use custom tag names:
// ❌ Wrong
Alias(tag: "appnexus", identity: id)  // Reserved, will be ignored

// ✅ Correct
Alias(tag: "my_appnexus_id", identity: id)
Problem: Same user appears as different users on different devices.Solution: Use consistent identifiers that work across devices:
// Best: Hashed email (works across all devices)
Alias(tag: "email_sha256", identity: hashedEmail, priority: 0)

// Good: Your internal user ID
Alias(tag: "internal_id", identity: userId, priority: 1)

Ad Integration Issues

Problem: googleCustomTargeting returns empty or minimal data.Solutions:
  1. Verify SDK is initialized before calling
  2. Check that cohorts exist for the user
  3. Wait for cohort data to sync after initialization
  4. Enable debug logging to see activations
Problem: prmtvvid key not in targeting dictionary.Solution: Pass the active PageTracker:
// ❌ Wrong - no view ID
Permutive.shared.googleCustomTargeting(adTargetable: nil)

// ✅ Correct - includes view ID
Permutive.shared.googleCustomTargeting(adTargetable: pageTracker)

TriggerProvider Issues

Problem: No callbacks when cohort membership changes.Solutions:
  1. Store a strong reference to TriggerAction:
    class MyController {
        // Store as property, not local variable
        private var trigger: TriggerAction?
    
        func setup() {
            trigger = Permutive.shared.triggerProvider?.action(...)
        }
    }
    
  2. Verify cohort IDs match your dashboard exactly
  3. Enable debug logging to see cohort updates
Problem: Trigger worked initially but stopped.Cause: TriggerAction reference was released.Solution: Keep TriggerAction as an instance property for the lifetime you need it.

Debug Logging

Enable comprehensive logging for troubleshooting:
guard let options = Options(
    apiKey: "<your-api-key>",
    organisationId: "<your-org-id>",
    workspaceId: "<your-workspace-id>"
) else { return }

// Enable all logging
options.logModes = LogMode.all

Permutive.shared.start(with: options) { error in
    // Check console for detailed logs
}

Log Messages to Look For

MessageMeaning
SDK readyInitialization successful
Accepted: X / XEvents sent successfully
event rejectionSchema validation failed
Schema validation failedProperty mismatch
Always disable debug logging in production builds to avoid performance overhead.
#if DEBUG
options.logModes = LogMode.all
#else
options.logModes = LogMode.none
#endif

Getting Help

If you can’t resolve an issue:
  1. Enable debug logging and capture relevant logs
  2. Check SDK version - ensure you’re on the latest
  3. Contact support:
Include in your support request:
  • SDK version
  • iOS/tvOS version
  • Xcode version
  • Relevant logs
  • Steps to reproduce