cometchat-ios-troubleshooting — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited cometchat-ios-troubleshooting (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Ground truth:CometChatUIKitSwift ~> 5(+CometChatCallsSDK ~> 5) — Pods/SPM.swiftinterface+ui-kit/ios. Official docs: https://www.cometchat.com/docs/ui-kit/ios/overview · Docs MCP:claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp(or fetch the URL directly without MCP). Verify symbols against the installed package/source before relying on them.
This skill helps diagnose and fix common issues when integrating CometChat iOS UI Kit. It covers build errors, runtime errors, and debugging techniques.
Cause: SDK not installed or not linked properly.
Solutions:
CocoaPods:
# Clean and reinstall
cd /path/to/your/project
rm -rf Pods Podfile.lock
pod install --repo-update
# Open workspace (not project!)
open YourApp.xcworkspaceSwift Package Manager:
Check Podfile:
platform :ios, '13.0'
use_frameworks!
target 'YourApp' do
pod 'CometChatUIKitSwift', '~> 5.1'
endCause: Core SDK not installed alongside UI Kit.
Solution: The UI Kit should include the SDK automatically. If not:
# Podfile
pod 'CometChatUIKitSwift', '~> 5.1'
pod 'CometChatSDK', '~> 4.0' # Add explicitly if neededCause: Calls SDK not installed but code references it.
Solutions:
# Podfile
pod 'CometChatCallsSDK', '~> 5.0'Wrap call-related code in conditional compilation:
#if canImport(CometChatCallsSDK)
import CometChatCallsSDK
// Call-related code here
#endifCause: Using wrong property for error description.
Solution: Use errorDescription instead of localizedDescription:
case .onError(let error):
print(error.errorDescription)
print(error.errorCode)CometChatException has:
errorDescription — human-readable error messageerrorCode — error code stringdetails — optional dictionary with additional infoCause: Trying to use CometChatException with Swift's Result<T, Error> type.
Solution: CometChatException does NOT conform to Swift's Error protocol. Don't use Result<T, Error> with CometChat callbacks. Instead, use direct callbacks:
// tier2-expect-error — this block intentionally demonstrates the compile error below
// ❌ WRONG - Don't use Result<T, Error>
func login(completion: @escaping (Result<User, Error>) -> Void) {
CometChatUIKit.login(uid: uid) { result in
switch result {
case .success(let user):
completion(.success(user))
case .onError(let error):
completion(.failure(error)) // ERROR: CometChatException is not Error
}
}
}
// ✅ CORRECT - Use CometChatException directly
func login(completion: @escaping (User?, CometChatException?) -> Void) {
CometChatUIKit.login(uid: uid) { result in
switch result {
case .success(let user):
completion(user, nil)
case .onError(let error):
completion(nil, error)
@unknown default:
completion(nil, nil)
}
}
}Cause: Neither class exists in the kit. They look like "pre-built composite UIViewControllers" but are NOT exported from CometChatUIKitSwift. Older docs and AI-generated guides sometimes claim they exist.
Solution: Compose your own MessagesVC from the real building blocks (CometChatMessageHeader + CometChatMessageList + CometChatMessageComposer). The pattern is the same one the kit's sample app uses (SampleApp/View Controllers/CometChat Components/MessagesVC.swift).
import CometChatUIKitSwift
import CometChatSDK
let conversations = CometChatConversations()
let navController = UINavigationController(rootViewController: conversations)
conversations.set(onItemClick: { [weak navController] conversation, _ in
let messagesVC = MessagesVC() // your own VC composing CometChatMessageHeader + List + Composer
if let group = conversation.conversationWith as? Group {
messagesVC.set(group: group)
} else if let user = conversation.conversationWith as? User {
messagesVC.set(user: user)
}
navController?.pushViewController(messagesVC, animated: true)
})See cometchat-ios-components § 13 ("Custom MessagesVC Implementation") for the full MessagesVC source.
Cause: CometChatCallLogs requires CometChatCallsSDK which is not installed.
Solutions:
# Podfile
pod 'CometChatCallsSDK', '~> 5.0'#if canImport(CometChatCallsSDK)
let callLogs = CometChatCallLogs()
#else
// Show placeholder or hide calls tab
#endifCause: Conflicting dependencies or duplicate frameworks.
Solutions:
rm -rf ~/Library/Developer/Xcode/DerivedDatapod deintegrate
pod installCause: Minimum iOS version mismatch.
Solution:
platform :ios, '13.0'pod installCause: Xcode sandbox permission issue (common in Xcode 15+).
Solution:
Podfile:post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
end
end
endpod installrm -rf ~/Library/Developer/Xcode/DerivedDataCause: Framework search paths issue.
Solution:
$(inherited) and $(PROJECT_DIR)/PodsCause: Trying to use CometChat before initialization completes.
Solution:
// ❌ Wrong - using before init completes
CometChatUIKit(uiKitSettings: settings) { _ in }
let conversations = CometChatConversations() // Too early!
// ✅ Correct - wait for completion
CometChatUIKit(uiKitSettings: settings) { result in
switch result {
case .success:
DispatchQueue.main.async {
let conversations = CometChatConversations()
// Now safe to use
}
case .failure(let error):
print("Init failed: \(error)")
}
}Cause: Wrong App ID or region.
Solutions:
let uiKitSettings = UIKitSettings()
.set(appID: "YOUR_APP_ID") // No spaces!
.set(region: "us") // Lowercase
.build()Cause: Wrong or expired Auth Key.
Solutions:
Cause: Trying to login with a UID that doesn't exist.
Solutions:
cometchat-uid-1 through cometchat-uid-5let user = User(uid: "new-user-123", name: "John Doe")
CometChatUIKit.create(user: user) { result in
switch result {
case .success(let user):
// Now login
CometChatUIKit.login(uid: user.uid ?? "") { _ in }
case .onError(let error):
print("Create failed: \(error)")
}
}Cause: Calling login when user is already logged in.
Solution:
// Check for existing session first
if let currentUser = CometChatUIKit.getLoggedInUser() {
print("Already logged in as: \(currentUser.name ?? "")")
// Proceed to chat UI
} else {
// Login
CometChatUIKit.login(uid: "user-123") { _ in }
}Cause: No conversations exist for the logged-in user.
Solutions:
if let user = CometChatUIKit.getLoggedInUser() {
print("Logged in as: \(user.uid ?? "")")
} else {
print("Not logged in!")
}let conversations = CometChatConversations()
conversations.set(onError: { error in
print("Error loading conversations: \(error.errorDescription ?? "")")
})
conversations.set(onEmpty: {
print("No conversations found")
})Cause: Various issues with message sending.
Solutions:
let composer = CometChatMessageComposer()
composer.set(user: user) // Must be set!composer.set(onError: { error in
print("Composer error: \((error as? CometChatException)?.errorDescription ?? "")")
})import Network
let monitor = NWPathMonitor()
monitor.pathUpdateHandler = { path in
if path.status == .satisfied {
print("Connected")
} else {
print("No connection")
}
}
monitor.start(queue: DispatchQueue.global())Cause: Multiple possible issues.
Checklist:
UNUserNotificationCenter.current().getNotificationSettings { settings in
print("Authorization status: \(settings.authorizationStatus.rawValue)")
}func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print("APNs Token: \(token)")
// Register with CometChat
CometChat.registerTokenForPushNotification(token: token, settings: ["voip": false]) { success in
print("Token registered: \(success)")
} onError: { error in
print("Token registration failed: \(error?.errorDescription ?? "")")
}
}Cause: Missing SDK or permissions.
Checklist:
pod 'CometChatCallsSDK', '~> 5.0'<key>NSCameraUsageDescription</key>
<string>Camera access for video calls</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access for calls</string>CometChatCallsSDK has no login/joinSession/SessionSettingsBuilder. The authority is the vendored CometChatCallsSDK.swiftinterface (generateToken / startSession / CallSettingsBuilder / CallsEventsDelegate). The calls-sdk-ios repo's own skills/ describe a different API and will mislead you — don't follow them. Default calling works through the UI Kit (CometChatUIKit calling-enabled) without a separate calls login; for custom calling, use generateToken → startSession.Cause: Missing privacy manifest, or an APNs-vs-FCM provider mismatch.
Fix:
.p8 + Team ID + Key ID, dev-vs-prod environment matching the build); if you route iOS through FCM, register with the FCM provider and the FCM_IOS platform. A token registered against the wrong provider silently never delivers. See cometchat-ios-push.Cause: Memory leaks or retain cycles.
Solutions:
conversations.set(onItemClick: { [weak self] conversation, _ in
self?.openMessages(for: conversation)
})override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
CometChatMessageEvents.removeListener("my-listener")
}Cause: Updates happening on background thread.
Solution:
// Always update UI on main thread
CometChatUIKit.login(uid: "user-123") { result in
DispatchQueue.main.async {
switch result {
case .success:
self.showConversations()
case .onError(let error):
self.showError(error)
}
}
}The CometChat iOS SDK has no public log-level API (there is no CometChat.setLogLevel / AppSettingsBuilder logging toggle). Diagnose by reading the CometChatException handed to each call's onError closure:
CometChat.init(appId: appID, appSettings: settings, onSuccess: { _ in
print("CometChat init OK")
}, onError: { error in
// CometChatException → code + message (init's onError is non-optional)
print("init failed:", error.errorCode, error.errorDescription)
})CometChat.addConnectionListener("debug-listener", self)
extension YourClass: CometChatConnectionDelegate {
func connected() {
print("✅ CometChat connected")
}
func connecting() {
print("🔄 CometChat connecting...")
}
func disconnected() {
print("❌ CometChat disconnected")
}
}class DebugMessageListener: CometChatMessageDelegate {
func onTextMessageReceived(textMessage: TextMessage) {
print("📩 Text message received: \(textMessage.text ?? "")")
}
func onMediaMessageReceived(mediaMessage: MediaMessage) {
print("📎 Media message received: \(mediaMessage.messageType)")
}
func onMessageDeleted(message: BaseMessage) {
print("🗑 Message deleted: \(message.id)")
}
}
CometChat.addMessageListener("debug-messages", DebugMessageListener())Use Charles Proxy or Proxyman to inspect CometChat API calls:
*.cometchat.ioBreakpoints:
Console:
// Print current state
print("User: \(CometChatUIKit.getLoggedInUser()?.uid ?? "none")")
print("Logged in: \(CometChatUIKit.getLoggedInUser() != nil)")| Code | Description | Solution |
|---|---|---|
ERR_UID_NOT_FOUND | User doesn't exist | Create user first |
ERR_ALREADY_LOGGED_IN | User already logged in | Check session before login |
ERR_NOT_LOGGED_IN | No active session | Login first |
AUTH_ERR_AUTH_TOKEN_NOT_FOUND | Invalid auth token | Generate new token |
ERR_INVALID_APP_ID | Wrong App ID | Verify in dashboard |
ERR_INVALID_API_KEY | Wrong API/Auth Key | Get correct key from dashboard |
ERR_BLOCKED_BY_EXTENSION | Blocked by extension | Check extension settings |
ERR_RATE_LIMIT_EXCEEDED | Too many requests | Implement rate limiting |
ERR_WEBSOCKET_CONNECTION_FAILED | Connection failed | Check network, retry |
Solutions:
let conversations = CometChatConversations()
conversations.set(conversationsRequestBuilder: ConversationRequest.ConversationRequestBuilder()
.set(limit: 20) // Reduce initial load
)Conversations automatically paginate. Ensure you're not fetching all at once.
Solutions:
let messageList = CometChatMessageList()
messageList.set(messagesRequestBuilder: MessagesRequest.MessageRequestBuilder()
.set(uid: user.uid ?? "")
.set(limit: 30) // Reduce initial load
)messageList.hideReceipts = true // If not needed
messageList.hideAvatar = true // If not neededSolutions:
// Don't keep strong references to dismissed VCs// CometChat handles image caching internally
// But you can clear URLCache if needed
URLCache.shared.removeAllCachedResponses()Cause: SwiftUI not detecting state changes.
Solution:
struct ChatView: View {
@State private var selectedConversation: Conversation?
var body: some View {
ConversationsWrapper(selectedConversation: $selectedConversation)
.onChange(of: selectedConversation) { newValue in
// Handle selection
}
}
}
struct ConversationsWrapper: UIViewControllerRepresentable {
@Binding var selectedConversation: Conversation?
func makeUIViewController(context: Context) -> CometChatConversations {
let vc = CometChatConversations()
vc.set(onItemClick: { conversation, _ in
selectedConversation = conversation
})
return vc
}
func updateUIViewController(_ uiViewController: CometChatConversations, context: Context) {
// Handle updates if needed
}
}Cause: Mixing UIKit navigation with SwiftUI.
Solution:
struct ChatNavigationView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
ConversationsView(onSelect: { conversation in
path.append(conversation)
})
.navigationDestination(for: Conversation.self) { conversation in
MessagesView(conversation: conversation)
}
}
}
}When something isn't working:
rm -rf ~/Library/Developer/Xcode/DerivedDatapod deintegrate && pod installCometChatException in each call's onError (errorCode + errorDescription) — the SDK has no log-level toggleCause: Incorrect property access for message bubble styles.
Solution: Message bubble styles use separate .incoming and .outgoing style objects, not combined properties:
// ✅ CORRECT - Use separate incoming/outgoing styles
CometChatMessageBubble.style.outgoing.backgroundColor = CometChatTheme.primaryColor
CometChatMessageBubble.style.incoming.backgroundColor = CometChatTheme.neutralColor300
// For text colors within bubbles
CometChatMessageBubble.style.outgoing.textBubbleStyle.textColor = .white
CometChatMessageBubble.style.incoming.textBubbleStyle.textColor = CometChatTheme.textColorPrimaryCause: Using incorrect property names for component styles.
Solution: Check the actual property names in the style struct:
// ✅ CORRECT ConversationsStyle properties
CometChatConversations.style.listItemTitleTextColor = CometChatTheme.textColorPrimary
CometChatConversations.style.listItemTitleFont = CometChatTypography.Heading4.medium
CometChatConversations.style.listItemSubTitleTextColor = CometChatTheme.textColorSecondary
CometChatConversations.style.listItemSubTitleFont = CometChatTypography.Body.regularCause: Using incorrect property names for composer style.
Solution: Use the correct property names:
// ✅ CORRECT MessageComposerStyle properties
CometChatMessageComposer.style.composeBoxBackgroundColor = CometChatTheme.backgroundColor01
CometChatMessageComposer.style.composeBoxBorderColor = CometChatTheme.borderColorDefault
CometChatMessageComposer.style.placeHolderTextColor = CometChatTheme.textColorTertiary
CometChatMessageComposer.style.textFiledColor = CometChatTheme.textColorPrimary
CometChatMessageComposer.style.activeSendButtonImageBackgroundColor = CometChatTheme.primaryColorCause: BadgeStyle.cornerRadius is CometChatCornerStyle?, not a simple value.
Solution:
// ✅ CORRECT - cornerRadius is optional CometChatCornerStyle
CometChatBadge.style.cornerRadius = CometChatCornerStyle(cornerRadius: 8)
// or nil for default pill shape
CometChatBadge.style.cornerRadius = nilCause: BadgeStyle.borderColor is CGColor, not UIColor.
Solution:
// ✅ CORRECT - use .cgColor
CometChatBadge.style.borderColor = UIColor.clear.cgColor
CometChatBadge.style.borderColor = UIColor.white.cgColorCause: Theme configured after UI is already displayed.
Solution: Configure theme before showing any CometChat UI:
// In AppDelegate or App init, BEFORE showing any CometChat views
func configureTheme() {
CometChatTheme.primaryColor = UIColor.systemBlue
CometChatTheme.backgroundColor01 = UIColor.systemBackground
// ... other theme settings
}
// Call this before CometChatUIKit.init()
configureTheme()Cause: Using incorrect property access for spacing values.
Solution: CometChatSpacing uses nested classes, not direct properties:
// ✅ CORRECT - Use nested class syntax
CometChatSpacing.Spacing.s1 = 4
CometChatSpacing.Spacing.s2 = 8
CometChatSpacing.Padding.p1 = 4
CometChatSpacing.Padding.p2 = 8
CometChatSpacing.Radius.r1 = 4
CometChatSpacing.Radius.r2 = 8
CometChatSpacing.Radius.rMax = 1000
CometChatSpacing.Margin.m1 = 4Cause: Missing type annotations in closures for custom views.
Solution: Always provide explicit type annotations for closure parameters:
import CometChatSDK
// ✅ CORRECT - Explicit type annotation
users.set(subtitle: { (user: User?) -> UIView in
let label = UILabel()
if user?.status == .online {
label.text = "Online"
label.textColor = .systemGreen
} else {
label.text = "Offline"
label.textColor = .gray
}
return label
})Note: Use set(subtitle:) method, not direct property assignment. The User type is from CometChatSDK.
Cause: Using wrong property name.
Solution: CometChatUsers uses subtitle, not subtitleView:
// ✅ CORRECT
users.set(subtitle: { (user: User?) -> UIView in
// Return custom view
})
// Different components use different names:
// - CometChatUsers: set(subtitle:)
// - CometChatConversations: set(subtitleView:)
// - CometChatMessageHeader: set(subtitleView:)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.