Skip to main content

Connection Issues

Failed to Connect to Room

Symptoms: Connection attempts fail or timeout. Solutions:
1

Verify URL and Token

Ensure your LiveKit server URL and JWT token are correct:
let url = "wss://your-livekit-server.com"  // Use wss:// for production
let token = "your_valid_jwt_token"

try await room.connect(url: url, token: token)
2

Check Network Connectivity

Verify your device has internet access and can reach the LiveKit server.
3

Enable Debug Logging

Increase log verbosity to diagnose connection issues:
// In App.init() or AppDelegate
LiveKitSDK.setLogLevel(.debug)
Logs are written to OSLog with category io.livekit.* and can be filtered in Xcode console.

Reconnection Failures

Symptoms: Room disconnects and fails to reconnect automatically. Solutions:
  • Check network stability and firewall settings
  • Implement reconnection delegate methods to handle state changes:
func room(_ room: Room, didUpdate connectionState: ConnectionState, from oldValue: ConnectionState) {
    switch connectionState {
    case .reconnecting:
        // Show reconnecting UI
    case .connected:
        // Connection restored
    case .disconnected:
        // Handle disconnect
    default:
        break
    }
}

Audio Issues

Microphone Not Publishing

Symptoms: Audio is not being transmitted to other participants. Solutions:
1

Check Permissions

Ensure microphone permission is granted. Add to Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone for video calls</string>
2

Verify AudioSession Configuration

If using manual audio session configuration, ensure it’s set to .playAndRecord:
let session = AVAudioSession.sharedInstance()
try session.setCategory(.playAndRecord, mode: .voiceChat)
try session.setActive(true)
3

Check Audio Engine State

Verify the audio engine is available before publishing:
try AudioManager.shared.setEngineAvailability(.default)
try await room.localParticipant.setMicrophone(enabled: true)

Audio Not Playing

Symptoms: Remote audio tracks are subscribed but no sound is heard. Solutions:
  • Verify device volume is not muted
  • Check AVAudioSession is active and configured correctly
  • Ensure audio category supports playback (.playback or .playAndRecord)

CallKit Integration Issues

Symptoms: Audio fails when using CallKit or conflicts occur. Solutions: Follow the proper CallKit integration pattern:
// Before connecting
AudioManager.shared.audioSession.isAutomaticConfigurationEnabled = false
try AudioManager.shared.setEngineAvailability(.none)

// In CXProviderDelegate
func provider(_: CXProvider, didActivate session: AVAudioSession) {
    do {
        try session.setCategory(.playAndRecord, mode: .voiceChat, options: [.mixWithOthers])
        try AudioManager.shared.setEngineAvailability(.default)
    } catch {
        // Handle error
    }
}

func provider(_: CXProvider, didDeactivate _: AVAudioSession) {
    do {
        try AudioManager.shared.setEngineAvailability(.none)
    } catch {
        // Handle error
    }
}
See the CallKit example for complete implementation.

Video Issues

Camera Not Publishing

Symptoms: Video track is created but no video is transmitted. Solutions:
1

Check Permissions

Ensure camera permission is granted. Add to Info.plist:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera for video calls</string>
2

Verify Camera Availability

Check that the device has a camera and it’s not in use by another app.
3

iOS Simulator Limitation

Publishing camera tracks is not supported on iOS Simulator. Test on a real device.

VideoView Not Rendering

Symptoms: VideoView is added but shows no video. Solutions:
  • Ensure track assignment is on the main thread:
DispatchQueue.main.async {
    self.videoView.track = track
}
  • Verify the VideoView has proper frame/constraints
  • Check that the track is actually publishing/receiving frames
  • Enable debug logging to see track state changes

Poor Video Quality

Symptoms: Video appears pixelated or low resolution. Solutions:
  • Adjust video encoding settings:
let encoding = VideoEncoding(
    maxBitrate: 2_000_000,  // 2 Mbps
    maxFps: 30
)

try await room.localParticipant.publish(
    videoTrack: track,
    publishOptions: VideoPublishOptions(encoding: encoding)
)
  • For 60 FPS camera:
let track = LocalVideoTrack.createCameraTrack(
    options: CameraCaptureOptions(fps: 60)
)

try await room.localParticipant.publish(
    videoTrack: track,
    publishOptions: VideoPublishOptions(encoding: VideoEncoding(maxFps: 60))
)

ScrollView Performance Issues

Symptoms: Poor performance when scrolling through multiple VideoViews. Solutions: Disable rendering for off-screen VideoViews:
// When cell goes off-screen
cell.videoView.isEnabled = false

// When cell comes back on-screen
cell.videoView.isEnabled = true
See the iOS platform guide ScrollView Performance section for a complete implementation pattern.

Memory Issues

Memory Leaks

Symptoms: Memory usage grows over time or Room doesn’t deallocate. Solutions:
1

Use Weak References

Always use weak references for SDK-managed objects:
weak var participant: RemoteParticipant?
weak var publication: TrackPublication?
2

Clean Up VideoView

The VideoView.track property doesn’t hold strong references, but it’s good practice to nil it:
videoView.track = nil
3

Disconnect Properly

Always disconnect from the room when done:
await room.disconnect()

Build Issues

macOS Catalina Crashes

Symptoms: App crashes on macOS Catalina with “ReplayKit not found”. Solution: If targeting macOS Catalina:
  1. Add ReplayKit.framework to Build Phases > Link Binary with Libraries
  2. Set it to Optional (not Required)
This is only required for macOS 10.15 Catalina. Apps targeting macOS 11.0+ do not need this.

App Store Submission - Missing DSYMs

Symptoms: Warning about missing dSYM for LiveKitWebRTC.framework. Solution: This is expected and will not prevent your app from being submitted or passing review. The LiveKitWebRTC.xcframework binary does not include DSYMs. If you need DSYMs (for custom builds), use the build script in DEBUG mode.

CocoaPods Deprecation

Warning: CocoaPods support is deprecated and will become read-only in 2027. Solution: Migrate to Swift Package Manager:
// Package.swift
dependencies: [
    .package(name: "LiveKit", url: "https://github.com/livekit/client-sdk-swift.git", .upToNextMajor("2.12.1"))
]

Screen Sharing Issues

Screen Share Not Working on macOS

Symptoms: Screen sharing gets stuck when display is turned off. Solution: This was fixed in SDK v2.8.0. Update to the latest version.

Broadcast Extension Issues

Symptoms: App crashes when moving to background during broadcast. Solution: Fixed in v2.10.2. Ensure you’re using the latest SDK version. For iOS screen sharing setup, see the iOS Screen Sharing guide.

Performance Optimization

High CPU Usage

Solutions:
  • Disable off-screen VideoViews (see ScrollView performance above)
  • Reduce video resolution/framerate if not needed
  • Use appropriate video codec settings
  • Monitor track statistics to identify bottlenecks

Reduce Mic Publish Latency

Solution: Pre-warm the audio engine:
AudioManager.shared.setRecordingAlwaysPreparedMode(true)

Getting Help

Community Support

Join our Slack community for help from devs and community members

GitHub Issues

Report bugs or request features on GitHub

FAQ

Check frequently asked questions

Documentation

Browse the complete LiveKit documentation

Debugging Tips

Enable Logging

// Set log level (call before any other LiveKit code)
LiveKitSDK.setLogLevel(.debug)

// Use custom logger
LiveKitSDK.setLogger(myCustomLogger)

// Disable logging completely
LiveKitSDK.disableLogging()

Capture Warning/Error Logs

Subclass OSLogger to capture specific log levels:
class MyLogger: OSLogger {
    override func log(level: LogLevel, message: String, file: String, function: String, line: Int) {
        if level == .warning || level == .error {
            // Send to your analytics/logging service
        }
        super.log(level: level, message: message, file: file, function: function, line: line)
    }
}

LiveKitSDK.setLogger(MyLogger())

Thread Safety Checks

  • All VideoView operations must be on the main thread
  • Delegates are called on SDK’s internal thread
  • Use @MainActor or DispatchQueue.main.async for UI updates

Build docs developers (and LLMs) love